高效併發之鎖優化

2021-09-26 22:26:03 字數 1806 閱讀 3976

前面討論執行緒間互斥同步的時候,提到了互斥同步對效能最大的影響是阻塞的實現,掛起執行緒和恢復執行緒操作都需要轉入核心態中完成,這些操作給系統的併發效能帶來了很大的壓力。共享資料的鎖定狀態只會持續很短一段時間,為了這段時間去掛起和恢復執行緒並不值得。如果物理機器有乙個以上的處理器,能讓兩個或以上的執行緒同時並行執行,我們就可以讓後面請求鎖的那個執行緒 「稍等一下」,但不放棄處理器的執行時間,看看持有鎖的執行緒是否很快就會釋放鎖。為了讓執行緒等待,我們只需讓執行緒執行乙個忙迴圈(自旋),這項技術就是所謂的自旋鎖。

自旋等待並不能代替阻塞,雖然自旋本身避免了切換執行緒的開銷,但它還是要占用處理器時間的,因此,如果鎖被占用的時間很短,自旋等待的效果就會非常好,反之,如果鎖占用的時間很長,那麼自旋的執行緒只會白白消耗處理器資源,而不會有任何有用的工作,反而會帶來效能上的浪費。因此,自旋等待的時間必須要有一定限度,如果自旋超過了限定次數仍然沒有成功獲得鎖,就應當使用傳統的方式去掛起執行緒了。自旋次數預設是 10 次,可以通過 -xx:preblockspin 來更改。

在 jdk 1.6 中引入了自適應的自旋鎖。自適應意味著自旋的時間不再固定了,而是由前一次在同乙個鎖上的自旋時間及鎖的擁有者的狀態來決定。如果在同乙個鎖物件上,自旋等待剛剛成功獲得過鎖,並且持有鎖的執行緒正在執行中,那麼虛擬機器就會認為這次自旋也很有可能再次成功,進而他將允許自旋等待持續相對更長的時間,比如100個迴圈。另外,如果對於某個鎖,自旋很少成功獲得過,那在以後要獲取這個鎖時將可能省略掉自旋過程,以避免浪費處理器資源。有了自適應自旋,隨著程式執行和效能監控資訊的不斷完善,虛擬機器對程式鎖的狀況**就會越來越準確,虛擬機器就會越來越 「聰明」 了。

鎖消除是指虛擬機器即時編譯器在執行時,對一些**上要求同步,但是被檢測到不可能存在共享資料競爭的鎖進行消除。鎖消除的主要判定依據**於逃逸分析的資料支援,如果判斷在一段**中,堆上的所有資料都不會逃逸出去從而被其他執行緒訪問到,那就可以把它們當作棧上資料對待,認為他們是執行緒私有的,同步加鎖自然就無須進行。比如下面一段**:

public string concatstring(string s1, string s2, string s3)
輕量級鎖是相對於使用作業系統互斥量來實現的傳統鎖(重量級鎖)而言的,輕量級鎖並不是用來代替重量級鎖的,他的本意是在沒有多執行緒競爭的前提下,減少傳統的重量級鎖使用作業系統互斥量產生的效能損耗。輕量級鎖的加鎖解鎖過程都是通過 cas 操作實現的。如果有兩條以上的執行緒爭用同乙個鎖那麼輕量級鎖就不再有效,要膨脹為重量級鎖。

輕量級鎖能提公升程式同步效能的依據是 「對於絕大部分的鎖,在整個同步週期內都是不存在競爭的」,這是乙個經驗資料。如果沒有競爭,輕量級鎖使用 cas 操作避免了使用互斥量的開銷,但如果存在鎖競爭,除了互斥量的開銷外,還額外發生了 cas 操作,因此在有競爭的情況下,輕量級鎖會比傳統的重量級鎖更慢。

偏向鎖也是 jdk 1.6 中引入的一項鎖優化,它的目的是消除資料在無競爭情況下的同步原語,進一步提高程式的執行效能。如果說輕量級鎖是在無競爭的情況下使用 cas 操作去消除同步使用的互斥量,那偏向鎖就是在無競爭的情況下把整個同步都消除掉,連 cas 操作都不做了。

偏向鎖的 「偏」 的意思是這個鎖會偏向於第乙個獲得他的執行緒,如果在接下來的執行過程中,該鎖沒有被其他的執行緒獲取,則持有偏向鎖的執行緒永遠不需要同步。

當有另外乙個執行緒去嘗試獲取這個鎖時,偏向模式就宣告結束。根據鎖物件目前是否處於被鎖定的狀態,撤銷偏向後恢復到未鎖定或輕量級鎖頂的狀態,後續的同步操作就如輕量級鎖那樣執行。

偏向鎖可以提高帶有同步但無競爭的程式效能。他同樣是乙個帶有效益權衡性質的優化,也就是說,他並不一定總是對程式執行有利,如果程式中大多數的鎖總是被多個不同的執行緒訪問,那偏向模式就是多餘的。有時候使用引數 -xx:-usebiasedlocking 來禁止偏向鎖優化反而可以提高效能。

Java高效併發(十) JVM中的鎖優化策略

比較交換演算法,cas操作包含三個引數cas v,e,n v表示要更新的變數,e表示預期值,n表示新值,當且僅當現在v的值等於e才會把v的值更新為n,如果在v的值不等於e,說明有執行緒對v做了更改,則cas更新失敗,對於更新失敗的執行緒可以繼續嘗試或者放棄更新。簡單的說就是你給出乙個期望值,如果變數...

Nginx 之併發優化

客戶端 服務端 連線數 ulimit n 100000 nginx 鏈結數 10240 個 worker connections 10240 允許開啟檔案數 worker processes 1 worker rlimit nofile 10000 系統的最大鏈結數 more proc sys ne...

Java併發之讀 寫鎖

讀取 沒有執行緒正在做寫操作且沒有執行緒請求寫操作 寫入 沒有執行緒正在做寫操作 這裡假設寫操作的優先順序比讀操作高 當乙個執行緒已經擁有寫鎖,才允許寫鎖重入 public class readwritelock writerequest writeaccesses writingthread ca...