在同一程式中執行多個執行緒本身不會導致問題,問題在於多個執行緒訪問了相同的資源。
如,同一記憶體區(變數,陣列,或物件)、系統(資料庫,web services等)或檔案。
實際上,這些問題只有在一或多個執行緒向這些資源做了寫操作時才有可能發生,
只要資源沒有發生變化,多個執行緒讀取相同的資源就是安全的。
多執行緒同時執行下面的**可能會出錯:
package com.lanhuigu.thread.demo2;
/** * 競態條件與臨界區
*/public class counter
}
假設執行緒a和b同時執行同乙個counter物件的add()方法,我們無法知道作業系統何時會在兩個執行緒之間切換。
jvm並不是將這段**視為單條指令來執行的,而是按照下面的順序:
(1) 從記憶體獲取 this.count 的值放到暫存器
(2) 將暫存器中的值增加value
(3) 將暫存器中的值寫回記憶體
觀察執行緒a和b交錯執行會發生什麼:
this.count = 0;
a: 讀取 this.count 到乙個暫存器 (0)
b: 讀取 this.count 到乙個暫存器 (0)
b: 將暫存器的值加2
b: 回寫暫存器值(2)到記憶體. this.count 現在等於 2
a: 將暫存器的值加3
a: 回寫暫存器值(3)到記憶體. this.count 現在等於 3
兩個執行緒分別加了2和3到count變數上,兩個執行緒執行結束後count變數的值應該等於5。
然而由於兩個執行緒是交叉執行的,兩個執行緒從記憶體中讀出的初始值都是0。然後各自加了2和3,並分別寫回記憶體。
最終的值並不是期望的5,而是最後寫回記憶體的那個執行緒的值,上面例子中最後寫回記憶體的是執行緒a,但實際中也可能是執行緒b。
如果沒有採用合適的同步機制,執行緒間的交叉執**況就無法預料。
競態條件 & 臨界區
當兩個執行緒競爭同一資源時,如果對資源的訪問順序敏感,就稱存在競態條件。
導致競態條件發生的**區稱作臨界區。上例中add()方法就是乙個臨界區,它會產生競態條件。
在臨界區中使用適當的同步就可以避免競態條件。
競態條件與臨界區
在同一程式中執行多個執行緒本身不會導致問題,問題在於多個執行緒訪問了相同的資源。如,同一記憶體區 變數,陣列,或物件 系統 資料庫,web services等 或檔案。實際上,這些問題只有在一或多個執行緒向這些資源做了寫操作時才有可能發生,只要資源沒有發生變化,多個執行緒讀取相同的資源就 是安全的。...
競態條件與臨界區
在同一程式中執行多個執行緒本身不會導致問題,問題在於多個執行緒訪問了相同的資源。如,同一記憶體區 變數,陣列,或物件 系統 資料庫,web services等 或檔案。實際上,這些問題只有在一或多個執行緒向這些資源做了寫操作時才有可能發生,只要資源沒有發生變化,多個執行緒讀取相同的資源就是安全的。多...
12 競態條件 時序競態
sleep函式幾點說明 1 sleep函式作用,讓程序睡眠。2 能被訊號打斷,然後處理訊號函式以後,就不再睡眠了。直接向下執行 3 sleep函式的返回值,是剩餘的秒數 sleep是可被中斷的睡眠,但不一定睡夠100s sleep是可中斷的睡眠 void handler int num if 1 v...