Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Multithreaded Java Program for Conway's game of life - contention at the border cells

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.

like image 990
Helen Avatar asked Feb 24 '10 19:02

Helen


2 Answers

I suggest having 2 int[][] arrays. Let's call them A and B. A will hold the values of all odd numbered "ticks" and B will hold the even numbered ticks.

Initialize A to whatever your initial state looks like. Then let your threads loose to calculate the next state of each cell, and place the results in the corresponding cell in B. Once all your threads are done, you have your new state in B. Now, use B to calculate the next state of each cell, and store the results in A. At any given time, one array will be read only, and the other write only, so there will never be any contention.

Advantages:

  • No copying of data compared to what you do now. Only one write is happening per cell.
  • No having to worry about edge/corner cases, as the algorithm is simple.
  • No ongoing allocation of memory. Just allocate the two arrays when you start.

Disadvantages:

  • You need to allocate twice as much memory.
like image 91
Peter Recore Avatar answered Oct 04 '22 19:10

Peter Recore


It doesn't answer your actual question, but my recommendation would be your first option... having the new values returned rather than having the worker threads update them. I'd take it a step further and have the "aggregator" combine the results from the worker threads into a new board state array and then discard the first one. My reasoning being that it will improve the overall readability of the logic, since there will be little to no "global interactions" you have to worry about.

That being said, I'm a bit biased because I prefer to program in a functional manner except when there's a strong reason not to.

like image 45
RHSeeger Avatar answered Oct 04 '22 18:10

RHSeeger