java多线程——锁优化

java多线程——锁优化

  • 引言
    在java高并发环境中,“锁”是最常用的同步方法,但是激烈的锁竞争以及不合理的加锁又会导致程序的性能下降,所以锁的优化就变成了一个重要的问题,具体的锁的优化包括减小锁粒度、锁分离等。
  • 减小锁的持有时间
    在锁的竞争当中,单个线程对锁的持有时间将会对整个程序的性能产生较大的影响。例如,银行排队去ATM机存钱,此时ATM机就是一个竞争的资源,只有一台机器供客户存钱,如果每个客户都等到进入ATM机处才开始从钱包里面拿钱、拿银行卡,再存钱,那么就会导致机器被占用的时间变得很长,从而对整个队列的性能产生影响。但是如果客户在进入ATM机之前就已经把银行卡和钱准备好拿在手中了,等到了ATM机处直接就开始存钱,这样就能减少每一个客户对资源的占用时间,进而提高队列的性能。程序的开发也是如此,我们应当尽量减少每个线程对锁的持有时间,以减少线程间互斥的可能。如下:
public synchronized void synMethod(){
	othercode1();
	mutexMethod();
	othercode2();
}

上述代码中,我们对整个方法做了同步控制,而方法内部只有mutexMethod()是互斥的资源,othercode1()、othercode2()并不需要去同步,当这两个代码块的耗时很长时,在这种同步控制方式下,会使cpu占用率变得很高,同时也会出现大量的等待线程。
但是,如果我们稍微修改一下上面的代码,就能将问题迎刃而解——对需要同步的地方加锁,而不是整个方法加锁。

public void synMethod(){
	othercode1();
	synchronized(this){
		mutexMethod();
	}
	othercode2();
}

这样就能明显的提升程序的性能,提升系统的吞吐量。实际上JDK源码中有很多地方就用到了此中优化策略,比如正则表达式中的Pattern类。
减少锁的持有时间有助于降低锁冲突的可能性,进而提升系统的并发能力。

  • 减小锁粒度
    所谓的减小锁粒度,其实就是缩小锁定对象的范围,从而减少所冲突的可能性,提高并发能力,我认为和减小锁的持有时间是有异曲同工之处的。最为典型的应用场景就是ConcurrentHashMap类的实现。
    对于ConcurrentHashMap其内部被细分为了若干个小的HashMap,称为段(Segement),默认情况下被细分为16个段。对于HashMap中最重要的方法就是put(),get()方法,在ConcurrentHashMap中,不是对整个HashMap进行加锁,而是首先对需要加入的元素求其hashcode得到它应该被放入哪一个段,然后再对段进行加锁,完成put()方法。
    注意: 减小锁粒度也会引发另一个问题,当系统需要取得全局锁的时候,会消耗比较多的资源。比如ConcurrentHashMap中的size()方法,即获取所有的有效表项的数量时,需要获得每一个段的锁才能返回最终的数量,这种情况下,效率是较低的。
    因此,减小锁粒度应该用在不会频繁的获得全局锁的应用场景中使用。
  • 读写分离锁替换独占锁
    该优化方法其实也是减小锁粒度的一种特殊情况,上面的减小锁粒度是从数据结构方面来进行的,而采用读写分离锁是对系统功能点的切割。
    读写分离锁在实际的开发中是很有必要的,因为系统在读数据的时候是不会破坏数据的完整性和一致性的,所以如果能允许多个线程同时读数据的话,就能节省不少的时间和降低冲突,这样读写锁就诞生了,只需要将读和写分离即可,读可以允许多个线程,而写只能一个一个的进行,读和写之间又是互斥的。具体约束如下:

在这里插入图片描述
读多写少的情况下,可以使用读写锁来有效提升系统的并发能力。

  • 锁粗化
    一般情况下,我们要求的是尽量减少线程对锁的持有时间,但是凡事都要有一个度,不能过度,否则只会适得其反,如果频繁的对一个锁进行请求,同步,释放,就其本身而言也是一种消耗,所以我们就要适当的对其进行锁粗化——即将多次对锁的操作合并成一次来进行,从而减少对锁的请求同步操作,具体例子如下:
forint i = 0;i < 10;i++{
	synchronized(lock){
		//待请求的资源
	}
}

显然,在上面的代码中,锁将被请求十次,这种情况下是没有必要每一次都去请求和释放锁的,所以我们可以将锁粗化,减少请求次数,如下:

synchronized(lock){
	forint i = 0;i < 10;i++{
		//待请求的资源
	}
}

锁粗化之后,就只需要请求和释放一次锁,完成十次循环,明显降低了请求次数,提高并发能力。
在实际的开发当中锁粗化和减少锁的持有时间是相反的,要在具体应用场景中具体考虑,选择最为合适的方案进行优化,权衡利弊。

  • 结束
    以上即是对锁的一些优化建议,如果还需要更进一步的了解和学习,可以参考《高并发程序设计一书》,其中有专门针对锁优化的章节讲解,希望大家不断学习,提升自己。
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值