首页 > 代码库 > Java 并发编程和可伸缩性(三)

Java 并发编程和可伸缩性(三)

避免热点域

比如一个hashmap的size。优化的方法就是加一个计数器。但是对于ConcurrentHashMap来说。当并发的对其进行操作时,每次put和remove都需要改变这个计数器。所以在这个类里这个计数器就被叫做热点域,是可伸缩性的瓶颈。所以这里采取避免热点域的方法是对于应用锁分段的散列桶,ConcurrentHashMap中的size将对每个分段进行枚举并将每个分段的元素数量相加。并通过每个分段的锁来维护这个值。

替代独占锁的方法

独占锁对性能的影响还是比较大的,不是所有同步的需求都必须使用独占锁来实现。

ReadWriteLock实现了一种在多读取操作以及单个写入操作情况下的加锁规则。

原子变量提供了一种降低更新热点域时的开销。例如静态计数器,序列发生器,或者对链表数据结构中头节点的引用。

监测CPU利用率

如果测试时,cpu没能充分发挥性能,那么就不能得到相对准确的结果,如果cpu没有得到充分利用需要找出其中的原因,通常是以下几种:

  • 负载不充足
  • I/O密集
  • 外部限制(数据库或web服务)
  • 锁竞争

向对象池说不

在早期的JVM中,对象的分配和垃圾回收的执行速度非常慢,所以许多开发人员使用对象池技术来解决这一问题。如今java中的对象内存分配速度已经比C语言还快了。所以这项技术如果你还在使用,并且应用在并发的程序中,已经可以考虑是不是应该放弃它了。因为它带来的锁竞争问题的开销远大于对象分配的开销。不过在J2ME或者RTSJ,需要对象池技术来提高内存管理或响应性管理的效率。


减少上下文的开销

第一点就是减少锁的持有时间。因为持有时间越短那么发生竞争的情况就越少,上下文切换的次数就少。反应在程序就是请求服务的时间不宜过长。

减少锁竞争的来源。比如通过把I/O操作从处理请求的线程转移到一个专门的线程。





Java 并发编程和可伸缩性(三)