并发性能和可伸缩性

线程的主要目的就是提高程序的运行性能。此外,线程还可以使程序在运行现有任务的情况下立即开始处理新的任务,从而提高系统的响应性。

性能的思考

提升性能意味着可以用更少的资源做更多的事情。但是提升性能会带来额外的复杂度,这会增加线程的安全性和活跃性上的风险。

我们渴望提升性能,但是还是要以安全为首要的。首先要保证程序能够安全正常的运行,然后在需要的时候进行性能优化。这个要求很类似于重构,呵呵

相较于单线程,多线程有很多独有的性能开销因素:

  • 线程之间的协调(如,加锁、内存同步等)
  • 增加的上下文切换
  • 线程的创建和销毁
  • 线程调度

由上可见,如果过度的使用线程,这些额外的开销可能会超过我们所做的性能提升。所以,要想合理的通过并发来提升性能,我们要注意:

  1. 更有效的利用现有处理资源
  2. 在出现新的处理资源时,使程序尽可能地利用这些资源

性能指标

性能存在有2种指标来衡量,分别是“多快”和“多少”。

1)服务时间、等待时间等指标,用来衡量程序的运行速度,即指定的任务需要“多快”才能处理完成。

2)生产量、吞吐量、可伸缩性等指标用于衡量程序的处理能力,即在计算资源一定的情况下,能完成“多少”工作。

这里可伸缩性指的是,当增加计算资源时(如CPU、内存、存储容量或带宽),程序的吞吐量或是处理能力能相应的提升。

根据可伸缩性定义我们可以猜测,如果可以无限制的增加资源,程序的处理能力是否可以无限制的提升?

答案肯定是不行的。我们可以根据Amdahl定律:

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

其中,F为程序中必须串行的部分,N为可以增加的处理器个数。

可见,在增加计算资源的情况下,程序理论上能够实现最高加速比,这个值取决于程序中可并行组件和串行组件所占的比重。

线程引入的开销

我们已经知道了,并行在带来性能提升的同时会带来由于并发而引起的开销。

上下文切换

如果可运行的线程多于CPU数,那么为了保证所有线程的运行,操作系统会将某个正在运行的线程调度出来,从而使其他线程可以使用CPU。这将会导致一次上下文切换,这个过程中将保存当前运行线程的执行上下文,并将新调度进来的线程的执行上下文设置为当前上下文。

内存同步

阻塞

JVM在实现阻塞时,可以采用自旋等待(通过循环不断地尝试获取锁,直到成功)或是通过操作系统挂起被阻塞的线程。

减少锁的竞争

减少锁的竞争可以提高性能和可伸缩性。这是由于独占锁,会导致其保护的资源串行执行。所以在并发程序中,对可伸缩性最大的威胁就是独占方式的资源锁。

有2中因素将会影响到锁竞争:

  • 锁的请求频率
  • 每次持有该锁的时间

如果上述2者的乘积很小,那么大多数锁的操作都不会发生竞争。

所以,可以总结出3种方式来降低锁的竞争程度:

  • 减少锁的持有时间
  • 降低锁的请求频率
  • 使用带有协调机制的独占锁

缩小锁的范围(快进快出)

尽可能缩短锁的持有时间,将一些与锁无关的程序移出同步代码块,只要确保原子性的操作在一个同步块中就好了

减小锁的粒度

降低线程请求锁的频率。可以通过锁分解和锁分段技术来实现,这些技术采用独立的锁来保护独立的状态变量,从而改变这些变量在之前由单个锁来保护的情况。但是要注意,随着锁越多,死锁的风险也就越高。

锁分解

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

锁分段

可以将锁分解技术进一步扩展为对一组独立对象上的锁进行分解,这种情况被称为锁分段。如,ConcurrentHashMap就使用了一个包含16个锁的数组,每个锁负责保护所有散列桶的1/16,这使得ConcurrentHashMap可以支持16个写入器同时写入。

锁分段也存在一个问题,如果执行toString或是hashCode之类的操作,需要锁定整个容器的时候,就需要获取所有的锁,这容易导致活跃性问题。

一些替代独占锁的方法

  1. 使用并发容器
  2. 读-写锁(ReadWriteLock),读操作可以同时访问该共享资源;写操作以独占的方式进行
  3. 原子变量

监测CPU的利用率

确保处理器可以得到充分利用。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值