性能包括:服务时间、延迟时间、吞吐率、效率、容量等 可伸缩性:当增长计算资源时(例如CPU、内存、存储容量或I/O带宽),程序的吞吐量或者处理能力能相应地增长 当进行性能调优时,其目的一般是用更小的代价完成相同的工做,例如经过缓存来重用以前计算的结果。 当进行可伸缩性调优时,其目的是设法将问题的计算并行化,从而能利用更多的计算资源来完成更多的工做。数组
在全部并发程序中都包含一些串行部分,若是你认为在你的程序中不存在串行部分,那么能够再仔细检查一遍。缓存
在并发程序中,对可伸缩性的最主要威胁就是独占方式的资源锁。有两个因素将影响在锁上发生竞争的可能性:锁的请求频率、每次持有该锁的时间。若是两者的乘积很小,那么大多数获取锁的操做都不会发生竞争,所以在该锁上的竞争不会对伸缩性形成严重影响。并发
有3种方式能够下降锁的竞争程度: 1. 减小锁的持有时间 2. 下降锁的请求频率 3. 使用带有协调机制的独占锁,这些机制容许更高的并发性
下降发生竞争可能性的一种有效方式就是尽量缩短锁的持有时间。例如能够将一些与锁无关的代码移出同步代码块,尤为是那些开销较大的操做,以及可能被阻塞的操做,例如I/O性能
下降线程请求锁的频率(从而减少发生竞争的可能性)。这能够经过锁分解和锁分段等技术来实现。在这些技术中将采用多个相互独立的锁来保护独立的状态变量,从而改变这些变量在以前由单个锁来保护的状况。 这些技术能减少锁操做的粒度,并能实现更高的可伸缩性,然而,使用的锁越多,那么发生死锁的风险也就越高。优化
若是一个锁须要保护多个相互独立的状态变量,那么能够将这个锁分解为多个锁,而且每一个锁只保护一个变量,从而提升可伸缩性,并最终下降每一个锁被请求的频率。
将锁分解技术进一步扩展为对一组独立对象上的锁进行分解,这种状况被称为“锁分段”。例如,在ConcurrentHashMap的实现中使用了一个包含16个锁的数组,每一个锁保护全部散列桶的1/16,其中第N个散列桶由第(N mod 16)个锁来保护。线程
锁分段的一个劣势在于:与采用单个锁来实现独占访问相比,要获取多个锁来实现独占访问将更加困难而且开销更高(在进行某些操做后,须要获取全部的锁)。
当每一个操做都请求多个变量时,锁的粒度将很难下降。这是在性能与可伸缩性之间相互制衡的另外一个方面。一些常见的优化措施,例如将一些反复计算的结果缓存起来,都会引入一些“热点域(Hot Field)”,而这些热点域每每会限制可伸缩性。code
另外一种下降锁竞争的技术就是放弃使用独占锁,从而有助于使用一种友好并发的方式来管理共享状态。例如,使用并发容器、读-写锁、不可变对象以及原子变量。对象
在许多任务中都包含一些可能被阻塞的操做。当任务在运行和阻塞这两个状态之间切换时,就至关于一次上下文切换。要提升性能,就要减小这样的切换。内存