天天看點

性能與可伸縮性(第十一章)

性能包括:服務時間、延遲時間、吞吐率、效率、容量等

可伸縮性:當增加計算資源時(例如CPU、記憶體、存儲容量或I/O帶寬),程式的吞吐量或者處理能力能相應地增加

在所有并發程式中都包含一些串行部分,如果你認為在你的程式中不存在串行部分,那麼可以再仔細檢查一遍。

上下文切換

記憶體同步

阻塞

在并發程式中,對可伸縮性的最主要威脅就是獨占方式的資源鎖。有兩個因素将影響在鎖上發生競争的可能性:鎖的請求頻率、每次持有該鎖的時間。如果二者的乘積很小,那麼大多數擷取鎖的操作都不會發生競争,是以在該鎖上的競争不會對伸縮性造成嚴重影響。

縮小鎖的範圍(“快進快出”)

降低發生競争可能性的一種有效方式就是盡可能縮短鎖的持有時間。例如可以将一些與鎖無關的代碼移出同步代碼塊,尤其是那些開銷較大的操作,以及可能被阻塞的操作,例如I/O

減小鎖的粒度

降低線程請求鎖的頻率(進而減小發生競争的可能性)。這可以通過鎖分解和鎖分段等技術來實作。在這些技術中将采用多個互相獨立的鎖來保護獨立的狀态變量,進而改變這些變量在之前由單個鎖來保護的情況。

這些技術能減小鎖操作的粒度,并能實作更高的可伸縮性,然而,使用的鎖越多,那麼發生死鎖的風險也就越高。

鎖分段

将鎖分解技術進一步擴充為對一組獨立對象上的鎖進行分解,這種情況被稱為“鎖分段”。例如,在ConcurrentHashMap的實作中使用了一個包含16個鎖的數組,每個鎖保護所有散列桶的1/16,其中第N個散列桶由第(N mod 16)個鎖來保護。

避免熱點域

當每個操作都請求多個變量時,鎖的粒度将很難降低。這是在性能與可伸縮性之間互相制衡的另一個方面。一些常見的優化措施,例如将一些反複計算的結果緩存起來,都會引入一些“熱點域(Hot Field)”,而這些熱點域往往會限制可伸縮性。

一些代替獨占鎖的方法

另一種降低鎖競争的技術就是放棄使用獨占鎖,進而有助于使用一種友好并發的方式來管理共享狀态。例如,使用并發容器、讀-寫鎖、不可變對象以及原子變量。

向對象池說“不”

在許多任務中都包含一些可能被阻塞的操作。當任務在運作和阻塞這兩個狀态之間切換時,就相當于一次上下文切換。要提高性能,就要減少這樣的切換。

繼續閱讀