Java并发教程–线程之间的可见性
當在不同線程之間共享對象的狀態時,除了原子性外,其他問題也會發揮作用。 其中之一是可見性。
關鍵事實是,如果沒有同步,則不能保證指令按照它們在源代碼中出現的順序執行。 這不會影響單線程程序中的結果,但是,在多線程程序中,如果一個線程更新值,則另一個線程可能在需要或不看到更新時看不到更新一切。
在多線程環境中,程序有責任確定何時在不同線程之間共享數據并采取行動(使用同步)。
NoVisibility中的示例包含兩個共享標志的線程。 編寫器線程更新標志,而讀取器線程等待直到設置標志:
public class NoVisibility {private static boolean ready;public static void main(String[] args) throws InterruptedException {new Thread(new Runnable() {@Overridepublic void run() {while (true) {if (ready) {System.out.println("Reader Thread - Flag change received. Finishing thread.");break;}}}}).start();Thread.sleep(3000);System.out.println("Writer thread - Changing flag...");ready = true;} }該程序可能會導致無限循環,因為讀取器線程可能看不到更新的標志并永遠等待。
通過同步,我們可以確保不會發生這種重新排序,從而避免了無限循環。 為了確保可見性,我們有兩種選擇:
- 鎖定:保證可見性和原子性(只要使用相同的鎖定)。
- 易揮發的字段:確保可見性。
volatile關鍵字的作用類似于某種同步塊。 每次訪問該字段時,就像輸入同步塊一樣。 主要區別在于它不使用鎖。 因此,它可能適用于上述示例(更新共享標志),但不適用于復合操作。
現在,我們通過將volatile關鍵字添加到ready字段來修改前面的示例。
public class Visibility {private static volatile boolean ready;public static void main(String[] args) throws InterruptedException {new Thread(new Runnable() {@Overridepublic void run() {while (true) {if (ready) {System.out.println("Reader Thread - Flag change received. Finishing thread.");break;}}}}).start();Thread.sleep(3000);System.out.println("Writer thread - Changing flag...");ready = true;} }可見性將不再導致無限循環。 作者線程進行的更新將對讀者線程可見:
Writer thread - Changing flag...
閱讀器線程-收到標志更改。 精加工螺紋。
結論
我們了解了在多線程程序中共享數據時的另一種風險。 對于一個簡單的示例(如此處所示),我們可以簡單地使用一個volatile字段。 其他情況將要求我們使用原子變量或鎖定。
- 您可以在github上查看源代碼。
翻譯自: https://www.javacodegeeks.com/2014/08/java-concurrency-tutorial-visibility-between-threads.html
總結
以上是生活随笔為你收集整理的Java并发教程–线程之间的可见性的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 苏州备案制教师与编制区别(苏州备案制教师
- 下一篇: 在CloudBees上开发,测试和部署独