ロックフリー プログラミングの主な問題は、アーキテクチャ レベルにあります。お互いのデータに干渉しないように、コードとアルゴリズムを設計する必要があります。個別に、特に個別に実行できる個々のタスクでコードを「ブロック」する必要があります。ただし、これらのアイデアに飛び込んでみると、なぜこれまで多くのブロッキングを使用していたのか疑問に思うようになります。
例: 与えられたのは文の配列であり、それぞれの単語を数えたいと考えており、それをスレッド方式で行いたいと考えています。
最初に、スレッドが衝突する可能性がある「チョークポイント」を特定する必要があります。この場合、データ ソース (配列) と、結果のカウントと最終的な println であるデータ出力です。そのため、これらのデータ ソースを同期またはロックせずにこれを行う方法を見つける必要があります。幸運なことに、Java は Atomics クラスを提供します。これにより、ブロックせずに同時アクセスが可能になり、多くのスマート コーディングが可能になります。
Array アクセスには 2 つのオプションがあります。AtomicInteger を Index として使用し、getAndIncremnt()
これにスレッドを配置して作業インデックスを取得できます。これは、スレッド数やデータ値の長さがわかっている場合に便利です (ヒント: 実際にはそうではありません)。
2 番目のオプションは、スレッドが他のスレッドに干渉しないようにする決定論的インデックスを最初から各スレッドに割り当てることです。つまり、4 つのスレッドと 256 のデータ値がある場合、インデックス値を 4 ずつ分配できます。つまり、スレッド A は 0、4、8、... スレッド B は 1、5、9、... などを取得します。の上。これにより、設計上、スレッドが他のスレッドと競合することはありません。
最後のカウントも同様に簡単です。最初にスレッドに内部で単語をカウントさせ、次に を使用して合計をグローバル AtomicInteger に追加しaddAndGet()
ます。
あとは、値を出力するタイミングを把握するだけです。答えは「最後のスレッドが完了したとき」です。これは - もう一度 - AtomicInteger をカウンターとして使用し、各スレッドdecrementAndGet()
を使用して、0 を取得したかどうかを確認することができます。これは、それらが最後のスレッドであり、結果を出力する必要があることを意味します。そして、ブロックする Barrier クラスを使用することもできますが、この時点ですべての作業が完了するため、もはや問題ではなくなります。