InterlockedXxx 関数の単純なケースを超えて、これらすべての一般的なパターンは、独自のロックを実装することです。
ここでの答えはどれも、「ロックフリー」のCASループとミューテックスまたはスピン ロックの違いの核心に到達しているようには見えません。
重要な違いは、ロックフリーアルゴリズムは、他のスレッドの支援なしに、独自に進行することが保証されていることです。ロックまたはスピン ロックでは、ロックを取得できない貧弱なスレッドは、ロックを所有するスレッドに完全に翻弄されます。ロックを取得できない貧弱なスレッドは、待機以外のことはできません(ビジー待機または OS 支援スリープのいずれかを介して)。
CAS でループするロックフリー アルゴリズムにより、競合する他のスレッドが何を行っているかに関係なく、各スレッドが確実に進行します。各スレッドは、本質的に、独自の運命を制御しています。はい、それでも何度もループする必要がありますが、ループの回数は競合するスレッドの数によって制限されます。ほとんどの場合、無限にループすることはできません。(実際には、たとえば、偽の共有が原因で失敗し続けるLL/SCループが原因でライブロックが発生する可能性があります) - ただし、これに対処するためにスレッド自体が対策を講じることができます - それは意のままではありませんロックを保持している別のスレッドの。
パフォーマンスに関しては、依存します。私は、スレッドの競合が激しい場合でも、ロックフリー アルゴリズムが対応するロック機能よりも完全にパフォーマンスが優れているという目に余る例を見てきました。Debian 7 を実行している x86-64 マシンで、C++ Boost.Lockfree キュー (Michael/Scott アルゴリズムに基づく) とstd::queue
、std::mutex
. スレッドの競合が多い状況では、ロックフリー バージョンはほぼ 2 倍遅くなりました。
では、それはなぜでしょうか。ロックフリー アルゴリズムのパフォーマンスは、最終的には実装の詳細に依存します。アルゴリズムはどのように ABA を回避しますか? 安全なメモリ再利用をどのように達成しますか? 非常に多くのバリアントがあります...タグ付きポインター、エポックベースの再生、RCU/静止状態、ハザードポインター、一般的なプロセス全体のガベージコレクションなど。これらすべての戦略にはパフォーマンスへの影響があり、アプリケーションの一般的な方法に制限を課すものもあります設計することができます。一般に、私の経験では、参照カウント アプローチ (またはタグ付きポインター アプローチ) はパフォーマンスが低下する傾向があります。ただし、代替手段は実装がはるかに複雑になる可能性があり、スレッドローカル ストレージまたは一般化されたガベージ コレクションに基づく、より多くのメモリ再利用インフラストラクチャが必要になります。