有助于提高鎖性能的幾點建議
-
減少鎖持有的時間
只在有必要的地方加鎖,這樣就能減少鎖的持有時間许起,增加系統(tǒng)的吞吐量
例如:在sycnMethon中只有mutextMethon方法需要加鎖蒂教,如果other code1與other code2都是重量級方法的話揖庄,就會花費較長的CPU時間阿逃。如果在高并發(fā)的情況下骡男,就會導致等待的線程不斷增加。
public synchronized void sycnMethon(){ othercode1(); mutextMethon(); othercode2(); }
解決方案:只在mutextMethon方法上加鎖夭谤,這樣可以減少鎖沖突的可能性棺牧,從而提升系統(tǒng)的吞吐量。
public void sycnMethon(){ othercode1(); synchronized(this){ mutextMethon(); } othercode2(); }
-
減小鎖粒度
所謂減小鎖粒度沮翔,就是縮小鎖定對象的范圍陨帆。
ConcurrentHashMap與HashTable如何將一個HashMap改造成一個線程安全的Map,我們知道HashTable是鎖定整個對象采蚀,而ConcurrentHashMap是鎖定一個段(也就是Hash Map的一部分)疲牵。所以說ConcurrentHashMap鎖粒度比Hashtable小。
讓我們來看一下ConcurrentHashMap怎樣減小鎖粒度的榆鼠。
ConcurrentHashMap內部被分為多個小的HashMap纲爸,稱之為段。在默認情況下妆够,一個ConcurrentHashMap被分為16個段识啦,如果需要在其中添加一個表項,不是將整個HashMap加上鎖神妹,而是根據(jù)該項的hashCode得到該表項被放在那個段颓哮,然后對該段進行加鎖,并完成put操作鸵荠。如果在多線程的情況下進行put操作冕茅,只要被加入的表項不是在同一個段,線程間便可以達到真正的并行蛹找。
-
用讀寫分離鎖(ReadWriteLock)來代替獨占鎖
在讀多少寫的情況下姨伤,讀寫鎖對系統(tǒng)很有好處。因為如果系統(tǒng)在讀寫數(shù)據(jù)的時候都用獨占鎖庸疾,那么讀與讀乍楚,讀與寫,寫與寫均不能做到并發(fā)届慈,并且需要等待徒溪,而讀操作不會影響到數(shù)據(jù)的完整性和一致性。因此金顿,在大部分情況下词渤,可以允許多線程同時讀,讀寫鎖體現(xiàn)了這個功能串绩。
-
鎖分離
如果將讀寫鎖再進一步延申,那就是鎖分離芜壁。讀寫鎖根據(jù)讀寫操作功能上不同礁凡,進行了有效的鎖分離高氮。根據(jù)相似的分離思想,也可以對獨占鎖進行分離顷牌。一個典型的案例就是LinkedBlockingQueue的實現(xiàn)剪芍。其內部有兩把鎖,一把是去的數(shù)據(jù)的鎖窟蓝,一把是放入數(shù)據(jù)的鎖罪裹。他們分別在take()和put()方法上使用。
/** Lock held by take, poll, etc */ private final ReentrantLock takeLock = new ReentrantLock(); /** Wait queue for waiting takes */ private final Condition notEmpty = takeLock.newCondition(); /** Lock held by put, offer, etc */ private final ReentrantLock putLock = new ReentrantLock(); /** Wait queue for waiting puts */ private final Condition notFull = putLock.newCondition();
雖然這兩個方法同時對當前隊列進行了修改操作运挫,但由于該隊列基于鏈表實現(xiàn)的状共,因此這兩個操作分別作用于隊列前端和尾端,兩者并不沖突谁帕。
如果使用獨占鎖峡继,take和put操作不能真正的并發(fā),在運行時匈挖,他們會互相等待對方釋放鎖碾牌,這種情況下競爭比較激烈,會影響系統(tǒng)在高并發(fā)情況下的性能儡循。
-
鎖粗化
如果對一個鎖不停的進行請求舶吗,同步和釋放,其本身也會消耗系統(tǒng)的資源择膝,反而不利于優(yōu)化誓琼。為此虛擬機對這種情況下,便會對所有鎖進行整合成對鎖的一次請求调榄,從而減少對鎖的請求次數(shù)踊赠。
例如:
public void demoMethon(){ synchronized (lock){ do sth } 做其他不需要同步的工作,但能很快執(zhí)行完畢 synchronized (lock){ do sth } }
上面代碼會被整合成這樣:
public void demoMethon(){ synchronized (lock){ do sth 做其他不需要同步的工作每庆,但能很快執(zhí)行完畢 do sth } }