我目前正在開發自己的小棋盤游戲,但遇到了多執行緒問題。我有一個渲染板的執行緒和一個提供要渲染的資料的執行緒。供應執行緒將他的資料寫入一個陣列,然后渲染器獲取此資料并將其渲染到螢屏上(渲染執行緒從不向陣列寫入任何內容)。因此,我開始閱讀有關執行緒之間的多執行緒和共享物件和陣列以及陣列上的 volatile 關鍵字的資訊,并發現使陣列 volatile 并不能解決問題。然后我讀到了happens-before關系,有點困惑。https://docs.oracle.com/javase/6/docs/api/java/util/concurrent/package-summary.html#MemoryVisibility說
監視器的解鎖(同步塊或方法退出)發生在同一監視器的每個后續鎖定(同步塊或方法入口)之前。并且由于happens-before關系是可傳遞的,因此執行緒在解鎖之前的所有動作都發生在任何執行緒鎖定該監視器之后的所有動作之前。
因此,如果我理解這一點正確,我將不得不以同步方法對陣列進行讀取和寫入,所以在這段代碼中,讀取器總是擁有寫入器寫入陣列的資料?
class Test {
private static String[] data = new String[10];
public synchronized String read(int index) {
return data[index];
}
public synchronized void write(String value, int index) {
data[index] = value;
}
private Thread writer = new Thread(() -> {
while(true) {
write("Test", 0);
System.out.println("Wrote " read(0) " to 0.");
try {
Thread.sleep(10000);
} catch (InterruptedException exc) {
//Handle exception
}
}
});
private Thread reader = new Thread(() -> {
while(true) {
System.out.println("Read " read(0) " from 0.");
try {
Thread.sleep(10000);
} catch (InterruptedException exc) {
//Handle exception
}
//Render the data
});
public static void main(String[] args){
writer.start();
reader.start();
}
}
謝謝。
PS。我不是母語人士,所以請原諒一些語法錯誤。
uj5u.com熱心網友回復:
AtomicReferenceArray將為您提供您正在尋找的語意。如此有效,一個具有易失元素的陣列。
用技術術語來說,如果對陣列中某個元素的讀取看到(相同元素的)寫入,則讀取將與該寫入同步。所以在寫和讀之間會有一個happens-before邊緣。
uj5u.com熱心網友回復:
您可以嘗試使用CopyOnWriteArrayList,但從您的描述看來 Queue 是最適合您需求的資料結構。您有一個資料生產者(您的供應商執行緒)和消費者(您的渲染器執行緒)。所以,看起來 Queue 真的給了你你需要的東西。閱讀Queue介面,并選擇您需要的佇列實作,可能是LinkedBlockingQueue
轉載請註明出處,本文鏈接:https://www.uj5u.com/qiye/419765.html
標籤:
上一篇:協程本質上是單執行緒的嗎?
