首先大家想一想,為什么要有鎖分解,鎖分段技術。
他們是用來解決什么的
前提:
在並發程序中,對可伸縮性的最主要威脅就是獨占方式的資源鎖。
可伸縮性
指的是: 當增加計算資源時(例如CPU,內存,存儲容器或者IO帶寬),程序的吞吐量或者處理能力會相應地增加。
串行操作會降低可伸縮性,並且上下文切換也會降低性能。在鎖上發生競爭時將同時導致這兩種問題,因此減少鎖的競爭能夠提高性能和可伸縮性。
有兩個因素將影響在鎖上發生競爭的可能性:鎖的請求頻率,以及每次持有該鎖的時間。如果兩者的乘積很小,那么大多數獲取鎖的操作都不會發生競爭,因此在該鎖上的競爭不會對可伸縮性造成嚴重影響。然而,如果在鎖上的請求量很高,那么需要獲取該鎖的線程將被阻塞並等待。
有3種方式可以降低鎖的競爭程度。
減少鎖的持有時間
降低鎖的請求頻率
使用帶有協調機制的獨占鎖,這些機制允許更高的並發性。
那么答案來了。鎖分解,鎖分段技術能夠降低線程請求鎖的頻率。
設想一下,如果在整個應用程序中只有一個鎖,而不是為每個對象分配一個獨立的鎖,那么所有同步代碼塊的執行就會變成串行化執行,而不考慮各個同步快中的鎖。
下面是書中的一個例子, 是用鎖分解技術來優化
未優化前:
優化后
鎖分解技術只適用於在鎖上存在適中而不是激烈的競爭時,
鎖分段:
如上面的例子,把一個競爭激烈鎖分解為兩個鎖時,這兩個鎖可能都存在激烈的競爭,雖然采用兩個線程並發執行能提高一部分的可伸縮性,但在一個擁有多個處理器的系統中,仍然無法給可伸縮性帶來極大的提高。
這時候,有另一種方法: 鎖分段技術。在某些情況下,可以將鎖分解技術進一步擴展為對一組獨立對象上的鎖進行分解,這種情況就被稱為鎖分段。例如jdk1.8之前的concurrentHashMap。
ConcurrentHashMap中有16個鎖的數組,每個鎖保護一個數組,16個數組彼此獨立,在這里大家可以思考一下,是不是跟上面鎖分解技術很像,只不過是另一種形式,
鎖分段有一個劣勢: