I’m currently working on my own little boardgame and came across a problem with multithreading. I have one thread that renders the board and one that supplies the data to render. The supply thread writes his data to one array and then the renderer takes this data and renders it on the screen (The render thread never writes something to the array). So I started to read about multithreading and shared objects and arrays between threads and the volatile keyword on arrays and found out that making an array volatile doesn’t solves the problem. Then I read about happens-before relations and got a little bit confused. https://docs.oracle.com/javase/6/docs/api/java/util/concurrent/package-summary.html#MemoryVisibility says that
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.
So if I understood this correct I would have to make the reads and writes to the array in a synchronized method, so in this code, the reader always has the data that the writer wrote to the array?
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(); } }
Thanks.
PS. I’m not a native speaker so please excuse some grammar mistakes.
Advertisement
Answer
The AtomicReferenceArray will give you the semantics you are looking for. So effectively, an array with volatile elements.
In technical terms, if the read of some element in the array sees a write (of the same element), then the read will synchronize with that write. So there will be a happens-before edge between the write and the read.