I am learning concurrent programming in java, and writing a simulation for Game of Life.
Here is what I am thinking:
- Use int[][] to store the states of the cells
- partition the int[][] into t segments and use t worker threads
- The t threads will read from their segment, calculate new values for all the cells in their segment and update the cells.
- Once they finished calculation they wait at a barrier for other workers to finish
- when the barrier is crossed the main thread will update the UI.
- the workers proceed to calculate the next state.
Now there is going to be contention at the common borders of the segments. If a thread overwrote the state of a border cell before its neighbor has read the previous value, the neighbor's calculation is going to be wrong.
What are my options?
- Use callable instead of runnable and have the worker threads return the new value (instead of updating the segments themselves). The main thread can update the matrix after the barrier is crossed. This option involves copying the results returned by worker threads into the matrix.
- Use two barriers. The workers thread make a copy of the border cells from their neighbors' segments and wait at the first barrier. Once this barrier is passed, they proceed to calculate the next states and update the segments in place. Then they wait at the 2nd barrier. the main thread updates the UI.
My question is, is there any other way to deal with the contention at the border cells that does not involve copying data or is more efficient that the above two options? May be using ReaderWriterLock, volatile variable or other synchronizing mechanism?
UPDATE: So far the double buffering solution by Peter is the cleanest one. But I have a question. Since the two arrays are shared data and we are not using any synchronization (synchronized access or volatile variable), won't it create visibility problem? Could multiple CPUs cache the array values and update only a part of the array with each iteration? Then the threads will get stale values for the border cells. Is this possible? If not, why. If yes, how do I solve it? It seems declaring two arrays volatile will not make their individual elements volatile.