1.减少锁持有的时间。
只在有必要时进行同步。
2.减少锁的粒度
分割数据结构
concurrentHashMap对应不同的区段segment进行加锁,减少锁锁定的范围。
concurrentHashMap 首先使用无锁的方式求和。如果失败了那么就使用加锁的方式求和。(先获取所有的锁,然后再求和,然后再释放)
3.使用读写锁替换独占锁
4.锁分离
如果将读写锁的思想做进一步的延申,那就是锁分离。
读写锁是根据读写操作功能上的不同,进行了有效的锁分离。
依据应用程序的功能特点,使用类似的分离思想,也可以对独占锁进行分离。
比如LinkedBlockingQueue中,实现take()和pu(),分别实现的是从队列中取得数据和增加数据的功能,虽然都是修改,但是两个操作是分别位于队列首端和队列尾端,两者并不冲突。
如果使用独占锁,那么要求两个操作进行时获取当前队列的独占锁,那么take(),put()都没办法真正比能发。在运行的是,都会彼此等待对方释放锁资源。
因此在jdk中取而代之是的是两把锁,分类take(),put()操作定义了takeLock()和putLock(),那么就可以同时写了。
5.锁粗化
虚拟机在遇到一连串联系对同一锁连续地对同一锁不断进行请求和释放的操作,便会把所有的锁操作整合成对锁的一次请求,从而减少对锁的请求同步次数,这个操作叫做锁粗化。
类似这样就没有必要。
public void askLock(){ Integer length = 10; for (int i = 0; i < length; i++) { synchronized (this) { } } }
应该
public synchronized void askLock(){ Integer length = 10; for (int i = 0; i < length; i++) { } }
Java虚拟机对锁优化所做的努力
锁偏向
好比你多次去一家店吃饭,吃得多了,老板记住了你吃饭前每次洗筷子,吃饭后每次都要开发票,这样的话,就是偏向你。
但是如果你每天都换饭店的话,那么根本都没有意义。
轻量级锁
无锁-轻量级锁-重量级锁
https://yq.aliyun.com/articles/49051