锁的性能与可伸缩性

一、资源密集型的操作定义

当操作性能由于某种特定的资源而受到限制时,我们通常将该操作称为资源密集型的操作。如,CPU密集型、数据库密集型。

二、多线程和单线程对比的缺点

尽管使用多个线程可以提升整体的性能,但是和单个线程相比,多线程会引入一定额外的开销,包括:线程之间的协调(加锁、触发信号、内存同步等)、增加上下文的切换、线程的创建和销毁,以及线程的调度等。

三、可伸缩性定义

当增加计算资源是(如CPU、内存、存储容量或IO带宽等),程序的吞吐量或者处理能力相应地增加。(类似于系统服务器的扩容)

四、Amdahl定律

在增加计算资源的情况下,程序理论上能够实现最高加速比,这个值取决于程序中可并行组件与串行组件所占的比重。假定F是必须被串行执行的部分,在包含N个处理器的机器中,最高的加速比为:

speedup<= 1 / (F + (1-F) / N)

当N趋于无穷大时,最大加速比趋于1/F.

所有并发程序中都包含一些串行部分。

五、线程引入的开销

1、上下文切换

上下文的切换会导致缓存的失效,因此调度器为每一个可运行的线程分配一个最小的执行时间,即是有许多的线程正在等待执行:它将上下文切换的开销分摊到更多不会中断的执行时间上,从而提高整体的吞吐量(以损失响应性为代价)。

上下文切换的开销相当于5000到10000个时钟周期,也就是几微妙。

Unix系统的vmstat和Windows上的perfmon命令能报告上下文切换的次数以及在内核中执行时间的占比。

2、内存同步

在synchronized和volatile提供的可见性保证中可能使用一些特殊的指令,即内存栅栏。内存栅栏可以刷新缓存,使得缓存失效,刷新硬件的写缓存,以及停止执行管道。

3、阻塞

在锁上发生竞争的时,竞争失败的线程肯定会阻塞。JVM在实现阻塞行为的时候可以 采用自旋等待(通过循环不断的尝试获取锁,知道成功)或者通过操作系统挂起被阻塞的线程。这两种方式的效率高低取决于上下文的开销以及在成功获取锁之前需要等待的时间。

 

六、减少锁的竞争

在并发程序中,对可伸缩性的主要威胁就是独占式的资源锁。

三种方式:

1、减少锁持有的时间;(压缩同步代码块的大小)

2、降低锁请求频率;(降低锁的粒度:锁分解和锁分段)

如果一个锁需要保护多个相互独立的状态变量,那么可以将这个锁分解为多个锁,并且每个锁只保护一个变量,从而提高伸缩性,并最终降低每个锁被请求的频率。

在某些情况下,可以将锁分解技术进一步扩展为一组独立对象上的锁进行分解,这种情况成为锁分段。例如、concurrentHashMap的底层实现,16段分段锁

3、使用带有协调机制的独占锁,这些机制允许更高的并发;(使用安全的类,比如原子操作类)

采用非独占的锁或者非阻塞锁来替代独占锁。

 

 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值