在 java 中的线程之间共享一个数组
Share an array between threads in java
我目前正在开发自己的小棋盘游戏,遇到了多线程问题。我有一个渲染板的线程和一个提供要渲染的数据的线程。供应线程将他的数据写入一个数组,然后渲染器获取该数据并将其渲染到屏幕上(渲染线程从不向数组写入任何内容)。所以我开始阅读有关线程之间的多线程和共享对象和数组以及数组上的 volatile 关键字的信息,发现使数组成为 volatile 并不能解决问题。然后我读到 happens-before 关系,有点困惑。 https://docs.oracle.com/javase/6/docs/api/java/util/concurrent/package-summary.html#MemoryVisibility 说
An unlock (synchronized block or method exit) of a monitor happens-before every subsequent lock (synchronized block or method entry) of that same monitor. And because the happens-before relation is transitive, all actions of a thread prior to unlocking happen-before all actions subsequent to any thread locking that monitor.
因此,如果我理解正确,我将不得不以同步方法对数组进行读取和写入,因此在这段代码中,reader 始终具有编写器写入数组的数据?
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。我不是母语人士,所以请原谅一些语法错误。
AtomicReferenceArray 将为您提供所需的语义。如此有效,一个包含易失性元素的数组。
在技术术语中,如果对数组中某个元素的读取看到(同一元素的)写入,则读取将与该写入同步。所以在写和读之间会有一个happens-before边。
您可以尝试使用 CopyOnWriteArrayList, but from what you describe seems that Queue is the data structure that fits your needs the most. You have a data producer (your supplier thread) and consumer (your renderer thread). So, seems like Queue really gives you what you need. Read about the Queue interface, and choose the queue implementation you need, probably LinkedBlockingQueue
我目前正在开发自己的小棋盘游戏,遇到了多线程问题。我有一个渲染板的线程和一个提供要渲染的数据的线程。供应线程将他的数据写入一个数组,然后渲染器获取该数据并将其渲染到屏幕上(渲染线程从不向数组写入任何内容)。所以我开始阅读有关线程之间的多线程和共享对象和数组以及数组上的 volatile 关键字的信息,发现使数组成为 volatile 并不能解决问题。然后我读到 happens-before 关系,有点困惑。 https://docs.oracle.com/javase/6/docs/api/java/util/concurrent/package-summary.html#MemoryVisibility 说
An unlock (synchronized block or method exit) of a monitor happens-before every subsequent lock (synchronized block or method entry) of that same monitor. And because the happens-before relation is transitive, all actions of a thread prior to unlocking happen-before all actions subsequent to any thread locking that monitor.
因此,如果我理解正确,我将不得不以同步方法对数组进行读取和写入,因此在这段代码中,reader 始终具有编写器写入数组的数据?
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。我不是母语人士,所以请原谅一些语法错误。
AtomicReferenceArray 将为您提供所需的语义。如此有效,一个包含易失性元素的数组。
在技术术语中,如果对数组中某个元素的读取看到(同一元素的)写入,则读取将与该写入同步。所以在写和读之间会有一个happens-before边。
您可以尝试使用 CopyOnWriteArrayList, but from what you describe seems that Queue is the data structure that fits your needs the most. You have a data producer (your supplier thread) and consumer (your renderer thread). So, seems like Queue really gives you what you need. Read about the Queue interface, and choose the queue implementation you need, probably LinkedBlockingQueue