java锁学习笔记
Posted ty_laurel
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了java锁学习笔记相关的知识,希望对你有一定的参考价值。
1.减小锁持有时间
减少锁的持有时间有助于降低锁冲突的可能性,进而提升系统的并发能力。即就是只在必要时进行同步,不需要同步操作的代码,尽量注意不要也加入需要同步的代码块中,这样就可以明显的减少线程持有锁的时间,提高系统的吞吐量。
2.减小锁粒度
减小锁粒度是一种削弱多线程锁竞争的有效手段。这种技术典型的使用场景就是ConcurrentHashMap类的实现。
ConcurrentHashMap内部进一步细分了若干个小的HashMap,称之为段(Segment)。默认一个ConcurrentHashMap被细分为16个段。
若需要在ConcurrentHashMap中增加一个新的表项,并不是将整个ConcurrentHashMap加锁,而是首先根据hashcode得到该表项应该被存放到哪个段中,然后对该段加锁,并完成put()操作。在多线程环境中,如果多个线程同时进行put()操作,只要被加入的表项不存在同一个段中,则线程间便可以做到真正的并行。
3.读写分离锁来替换独占锁ReadWriteLock
读操作本身是不会影响数据的完整性和一致性的,多个线程可以同时对同一个数据进行读操作,而写操作由于要更改数据,在多线程中需要进行同步操作。因而读写锁适用于读多写少的场景,可以有效提升系统的并发能力和减小锁的粒度。
4.锁分离
将读写锁的思想做进一步的延伸,就是锁分离。读写锁根据读写操作功能上的不同,进行了有效的锁分离。那么依据应用程序的功能特点,同样的思想,也可以对独占锁进行分离。例如java.util.concurrent.LinkedBlockingQueue的实现。
在LinkedBlockingQueue实现中,take()函数和put()函数分别实现了从队列中取得数据和往队列中增加数据的功能。虽然两个函数操作都是对当前队列进行修改操作,但由于LinkedBlockingQueue是基于链表的,因此,两个操作分别作用域队列的前端和尾端,从理论上来说,两者并不冲突。而对于ArrayBlockingQueue来说是基于数组的,take、put仍共用同一把锁。
5.锁粗化
粗化即就是尽量的减少锁的使用,当JVM虚拟机在遇到一连串连续地对同一锁进行请求和释放的操作时,便会把所有的锁操作整合成对锁的一次请求,从而减少对锁的请求同步次数。在开发过程中,应该有意识地在合理的场合进行锁的粗化,尤其在循环中请求锁。
性能优化就是根据运行时的真实情况对各个资源点进行权衡折中的过程。锁粗化的思想和减少锁持有时间是相反的,但在不同的场合,它们的效果并不相同,需要根据具体的实际情况进行权衡。
以上是关于java锁学习笔记的主要内容,如果未能解决你的问题,请参考以下文章