Java で並行プログラミングを学んでいて、Game of Life のシミュレーションを書いています。
これが私が考えていることです:
- int[][] を使用してセルの状態を保存します
- int[][] を t 個のセグメントに分割し、t 個のワーカー スレッドを使用する
- t スレッドはセグメントから読み取り、セグメント内のすべてのセルの新しい値を計算し、セルを更新します。
- 計算が終了すると、障壁で他のワーカーが終了するのを待ちます
- バリアを越えると、メイン スレッドが UI を更新します。
- ワーカーは次の状態の計算に進みます。
現在、セグメントの共通の境界で競合が発生しています。隣接セルが前の値を読み取る前にスレッドが境界セルの状態を上書きした場合、隣接セルの計算は間違っています。
私のオプションは何ですか?
- runnable の代わりに callable を使用し、ワーカー スレッドが新しい値を返すようにします (セグメント自体を更新するのではなく)。バリアを越えた後、メイン スレッドはマトリックスを更新できます。このオプションでは、ワーカー スレッドによって返された結果をマトリックスにコピーします。
- 2 つのバリアを使用します。ワーカー スレッドは、隣接するセグメントから境界セルのコピーを作成し、最初のバリアで待機します。このバリアを通過すると、次の状態の計算に進み、その場でセグメントを更新します。その後、2 番目のバリアで待機します。メイン スレッドが UI を更新します。
私の質問は、データのコピーを伴わない、または上記の 2 つのオプションよりも効率的な境界セルでの競合に対処する他の方法はありますか? ReaderWriterLock、揮発性変数、またはその他の同期メカニズムを使用している可能性がありますか?
更新: これまでのところ、Peter によるダブル バッファリング ソリューションが最もクリーンなソリューションです。しかし、質問があります。2 つの配列は共有データであり、同期 (同期アクセスまたは揮発性変数) を使用していないため、可視性の問題は発生しませんか? 複数の CPU が配列の値をキャッシュし、各反復で配列の一部のみを更新できますか? 次に、スレッドは境界セルの古い値を取得します。これは可能ですか?そうでない場合は、その理由。はいの場合、どうすれば解決できますか? 2 つの配列を volatileと宣言しても、個々の要素が volatile にならないようです。