Java如何在臨界區中避免競態條件
當兩個執行緒競爭同一資源時,如果對資源的訪問順序敏感,就稱存在競態條件。導致競態條件發生的程式碼區稱作臨界區。在臨界區中使用適當的同步就可以避免競態條件。
界區實現方法有兩種,一種是用synchronized,一種是用Lock顯式鎖實現。synchronized 關鍵字,代表這個方法加鎖,相當於不管哪一個執行緒(例如執行緒A),執行到這個方法時,都要檢查有沒有其它執行緒B(或者C、 D等)正在用這個方法(或者該類的其他同步方法),有的話要等正在使用synchronized方法的執行緒B(或者C 、D)執行完這個方法後再執行此執行緒A,沒有的話,鎖定呼叫者,然後直接執行。它包括兩種用法:synchronized 方法和 synchronized 塊。
Java語言的關鍵字,可用來給物件和方法或者程式碼塊加鎖,當它鎖定一個方法或者一個程式碼塊的時候,同一時刻最多隻有一個執行緒執行這段程式碼。當兩個併發執行緒訪問同一個物件object中的這個加鎖同步程式碼塊時,一個時間內只能有一個執行緒得到執行。另一個執行緒必須等待當前執行緒執行完這個程式碼塊以後才能執行該程式碼塊。然而,當一個執行緒訪問object的一個加鎖程式碼塊時,另一個執行緒仍可以訪問該object中的非加鎖程式碼塊。
有臨界區是為了讓更多的其它執行緒能安全夠訪問資源。
class Counter { protected long count = 0; public void add(long value) { this.count = this.count + value; } }
觀察執行緒A和B交錯執行會發生什麼,兩個執行緒分別加了2和3到count變數上,兩個執行緒執行結束後count變數的值應該等於5。然而由於兩個執行緒是交叉執行的,兩個執行緒從記憶體中讀出的初始值都是0。然後各自加了2和3,並分別寫回記憶體。最終的值並不是期望的5,而是最後寫回記憶體的那個執行緒的值,上面例子中最後寫回記憶體的是執行緒A,但實際中也可能是執行緒B。如果沒有采用合適的同步機制,執行緒間的交叉執行情況就無法預料。
add()方法就是一個臨界區,它會產生競態條件。
以上就是本文的全部內容,希望對大家的學習有所幫助,也希望大家多多支援我們。