線程通訊,主要經過共享訪問進程資源。這種通訊方式很是高效,但存在兩個問題:線程衝突(thread interference) , 內存一致性錯誤(memory consistensy errors)。java
解決這兩種問題的方法是 線程同步(thread synchronization)。在介紹線程同步以前,先來了解一下這兩個問題。app
這篇文章介紹第二個問題:內存一致性錯誤。線程
Memory consistency errors occur when different threads have inconsistent views of what should be the same data.code
當不一樣的線程對於同一個數據有不一致的值時,產生內存一致性錯誤(Memory consistency errors)進程
產生 memory consistency error 的緣由稍複雜,不過咱們並不須要知道這其中的細節,只須要知道如何避免該錯誤。內存
要避免 memory consistency error,須要理解 happens-before 關係。這個關係是一個簡單的保證,保證當內存被一個特定的操做修改時,對於另外一個操做是可見的。資源
注:參考下邊的例子,再回來理解上邊的內容同步
令一個屬性 couter
聲明並初始化io
int counter = 0;
這個 counter
被線程 A 和線程 B 共享class
假定線程 A 對 couter
的操做爲
couter++;
假定線程 B 對 couter
的操做爲
System.out.println(couter);
若是上述兩個操做在同一個線程,則能夠確定,最終輸出的結果爲1。但這兩個操做分別在兩個線程中執行,線程 B 最終輸出的結果可能爲0,由於沒法保證線程 A 對 couter 的操做對於 B 是可見的 —— 即 B 沒法判斷 A 是否正在修改值
除非咱們爲 A 和 B 創建一個 happens-before
關係。
創建 happens-before
關係,方法就是 線程同步(Thread Synchronization)。這在另外一個文章中詳談。
其實咱們已經已經見過這種 happens-before
關係
當一個語句調用 Thread.start 建立新線程時,該語句以後的操做不只和該語句有了 happens-before 關係,且和新線程中的 run 方法包含的全部操做都有了 happens-before 關係 —— 簡單的說,就是主線程已知一個新線程要運行,對此主線程能夠作一些處理,好比調用新線程的 Thread.join 方法等待其運行結束。
Thread.join 同理。