多线程-性能

性能

多线程并发的优势可以提高程序性能,但增加了线程之间的协调(加锁、触发信号以及内存同步)、增加上下文切换线程的创建和销毁以及线程的调度等时间 。性能衡量的单位非服务时间,而是吞吐量和伸缩性.

上下文切换:许多并发线程中都会出现阻塞操作。而从阻塞状态转换成运行状态这过程称为上下文切换

吞吐量:单位时间内处理任务数量。

伸缩性:当增加计算机资源配置时(如内存,CPU,存储容量或者IO带宽),程序的吞吐量和处理能力相应提高。

当多线程并行化处理任务时,总会包含一些串行化部分。而串行化部分会限制程序的吞吐量。比如应用程序中有多个线程处理共享的同步阻塞队列中的任务,此队列通过加锁来保护队列的状态即取出任务后会阻塞下一个任务。那么此时增加计算机资源比如增加处理器,程序的并发处理任务并不会因此增加。因为此时最大的瓶颈在于队列竞争锁同步方法中,即串行化部分。如果当串行化部分即同步方法在并行化中占比越高,则代表程序的伸缩性则越低。结论:串行化占程序的比例影响了程序的吞吐量和伸缩性。

如果想提高吞吐量和伸缩性的话,则必须减少串行化代码在程序中的占比。而串行化代码即同步代码大部分是竞争资源独占锁组成。而运行资源占锁的总时间分为竞争锁的时间以及获取锁后执行代码的时间。减少资源占锁的总时间有以下三种方式:

  1. 减少锁竞争
  2. 减少锁持有的时间
  3. 用并发性更高的方法替换独占锁
减少锁竞争

线程之间竞争锁会发生线程阻塞,阻塞则会增加处理的时间。减少锁竞争可以通过减小锁的粒度,具体方法用锁分段以及锁分解方法实现。比如JDK7中并发集合ConcurrentHashMap中通过分段锁来减少锁的粒度,从而减低了锁竞争,增加了并发处理速度。锁分解是将一个锁分解为多个锁,能最大限度的提升性能。

减少锁持有的时间

锁持有的时间即执行同步方法的时间。所以我们通过减少执行同步代码时间而减少锁持有的时间。具体可以将非同步或多余的代码移出同步代码方法中,尤其是开销较多的操作以及被阻塞的操作。如IO操作。

用并发性更高的方法替换独占锁

降低锁影响的技术就是放弃独占锁,用一种并发性更高的方法来管理共享状态。例如用并发容器,读写锁,不可变的对象以及原子变量。

ReadWriteLock。读写锁类似mysql中的排他锁,只有在执行写入操作时需要竞争独占锁方式,而读操作不需要竞争锁就可以读取。这样当提高了读写的效率,从而提高了并发性。所以用并发性比独占锁高的读写锁替代。

原子变量。原子变量提供了对变量更加细粒度的锁控制,并使用CAS(compare-and-swap)原子操作。

小结

程序并发性能高低是由吞吐量伸缩性所衡量。而伸缩性的高低由串行化代码占系统的比例决定。而大部分串行化代码都是由独占锁产生。而减少独占锁时间有三种方式,第一种减少锁竞争,第二种减少持有锁的时间,第三种是用并发行更高的方法替代独占锁。

##


评论

Your browser is out-of-date!

Update your browser to view this website correctly. Update my browser now

×