Java 并发编程和可伸缩性(三)
避免热点域
比如一个hashmap的size。优化的方法就是加一个计数器。但是对于ConcurrentHashMap来说。当并发的对其进行操作时,每次put和remove都需要改变这个计数器。所以在这个类里这个计数器就被叫做热点域,是可伸缩性的瓶颈。所以这里采取避免热点域的方法是对于应用锁分段的散列桶,ConcurrentHashMap中的size将对每个分段进行枚举并将每个分段的元素数量相加。并通过每个分段的锁来维护这个值。
替代独占锁的方法
独占锁对性能的影响还是比较大的,不是所有同步的需求都必须使用独占锁来实现。
ReadWriteLock实现了一种在多读取操作以及单个写入操作情况下的加锁规则。
原子变量提供了一种降低更新热点域时的开销。例如静态计数器,序列发生器,或者对链表数据结构中头节点的引用。
监测CPU利用率
如果测试时,cpu没能充分发挥性能,那么就不能得到相对准确的结果,如果cpu没有得到充分利用需要找出其中的原因,通常是以下几种:
- 负载不充足
- I/O密集
- 外部限制(数据库或web服务)
- 锁竞争
向对象池说不
在早期的JVM中,对象的分配和垃圾回收的执行速度非常慢,所以许多开发人员使用对象池技术来解决这一问题。如今java中的对象内存分配速度已经比C语言还快了。所以这项技术如果你还在使用,并且应用在并发的程序中,已经可以考虑是不是应该放弃它了。因为它带来的锁竞争问题的开销远大于对象分配的开销。不过在J2ME或者RTSJ,需要对象池技术来提高内存管理或响应性管理的效率。
减少上下文的开销
第一点就是减少锁的持有时间。因为持有时间越短那么发生竞争的情况就越少,上下文切换的次数就少。反应在程序就是请求服务的时间不宜过长。
减少锁竞争的来源。比如通过把I/O操作从处理请求的线程转移到一个专门的线程。
郑重声明:本站内容如果来自互联网及其他传播媒体,其版权均属原媒体及文章作者所有。转载目的在于传递更多信息及用于网络分享,并不代表本站赞同其观点和对其真实性负责,也不构成任何其他建议。