2017-08-11 76 views
2

我寫一些代碼,其中爪哇 - 同一個對象,不同的變量,多線程

class A { 
    Integer x; 
    String y 
} 

我創建了一個對象,我把它傳遞給2級運行的線程。第一個線程更新值x,而第二個更新值y。

有沒有這種情況可以打破?我的意思是,如果有兩個線程更新同一對象的不同變量,是否會出現競態條件?

+2

爲什麼你需要單個對象呢?將不同的對象傳遞給不同的線程 –

+1

是的,有很多這種情況可能會中斷。你需要閱讀http://jcip.net/ – Oleg

+1

哪個線程是讀取數據的? –

回答

0

不,它會正常工作。只要任何給定的變量只被一個線程更新(在其他線程讀取該變量時有一些條件),你就沒事了。

它可能不是最理解的設計,取決於你在做什麼 - 另外,正如我上面提到的,不要指望從另一個線程可靠地讀取這些變量,如果你想要看看原子對象或易揮發。 (原子會從多個線程寫入更快,揮發性仍可能更好,如果你只是從一個線程寫,別人讀)

+2

這個答案就像一個handwave:「其他線程讀取變量的一些條件」是最重要的部分!在所描述的場景中可能會出現很多非顯而易見的行爲,具體取決於'x'和'y'被讀取的位置,這是這裏的重要部分。 –

0

多線程不僅是比賽條件下,它也是關於通過
jsr-133制定存儲可視性如果您想了解java中的併發性,您絕對必須學習這些知識。

有些情況下,你的代碼可以打破可能很多方面,一個明顯的例子是,如果你在線程創建的對象在線程C-線程B和Y的變化X你可能永遠不會看到線程A這些變化

一些代碼來說明:

A a = new A(); 
a.x = 0; 

Thread t1 = new Thread(() -> { 
    while (true) { 
     a.x = 1; 
    } 
}); 

Thread t2 = new Thread(() -> { 
    a.y = "a"; 
}); 

t1.start(); 
t2.start(); 

while(a.x == 0) { 
} 

System.out.println("might never get here"); 

一個可能的解決辦法是讓X和Y揮發性

class A { 
    volatile Integer x; 
    volatile String y; 
} 

這將確保所有線程看到改變x和y但您仍然需要確保A的實例已安全發佈。

+0

@BillK「如果作者僅僅是從兩個線程寫入不同的變量,那麼他很好」**絕對不是!!! **不確保寫入將被正確地看到,他將以意外的行爲和不正確的值結束。我制定了一個符合他的問題和休息的場景(至少可以休息,實際上很難看到它發生)。 – Oleg