我寫一些代碼,其中爪哇 - 同一個對象,不同的變量,多線程
class A {
Integer x;
String y
}
我創建了一個對象,我把它傳遞給2級運行的線程。第一個線程更新值x,而第二個更新值y。
有沒有這種情況可以打破?我的意思是,如果有兩個線程更新同一對象的不同變量,是否會出現競態條件?
我寫一些代碼,其中爪哇 - 同一個對象,不同的變量,多線程
class A {
Integer x;
String y
}
我創建了一個對象,我把它傳遞給2級運行的線程。第一個線程更新值x,而第二個更新值y。
有沒有這種情況可以打破?我的意思是,如果有兩個線程更新同一對象的不同變量,是否會出現競態條件?
不,它會正常工作。只要任何給定的變量只被一個線程更新(在其他線程讀取該變量時有一些條件),你就沒事了。
它可能不是最理解的設計,取決於你在做什麼 - 另外,正如我上面提到的,不要指望從另一個線程可靠地讀取這些變量,如果你想要看看原子對象或易揮發。 (原子會從多個線程寫入更快,揮發性仍可能更好,如果你只是從一個線程寫,別人讀)
這個答案就像一個handwave:「其他線程讀取變量的一些條件」是最重要的部分!在所描述的場景中可能會出現很多非顯而易見的行爲,具體取決於'x'和'y'被讀取的位置,這是這裏的重要部分。 –
多線程不僅是比賽條件下,它也是關於通過
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的實例已安全發佈。
@BillK「如果作者僅僅是從兩個線程寫入不同的變量,那麼他很好」**絕對不是!!! **不確保寫入將被正確地看到,他將以意外的行爲和不正確的值結束。我制定了一個符合他的問題和休息的場景(至少可以休息,實際上很難看到它發生)。 – Oleg
爲什麼你需要單個對象呢?將不同的對象傳遞給不同的線程 –
是的,有很多這種情況可能會中斷。你需要閱讀http://jcip.net/ – Oleg
哪個線程是讀取數據的? –