プロジェクトを設計する場合、マルチスレッドを処理するために使用できる手法はたくさんあります。
最も一般的で普遍的なのは、単に「共有状態を回避する」ことです。可能な限り、同じ共有コピーにアクセスさせるのではなく、スレッド間でリソースをコピーします。
低レベルの同期コードを自分で作成している場合は、まったく想定しないことを忘れないでください。コンパイラとCPUの両方がコードを並べ替えて、コードの読み取り時に競合状態やデッドロックが発生する可能性があります。これを防ぐ唯一の方法は、メモリバリアを使用することです。また、最も単純な操作でもスレッドの問題が発生する可能性があることに注意してください。++i
通常はアトミックではないほど単純なものであり、複数のスレッドがアクセスするi
と、予測できない結果が得られます。もちろん、変数に値を割り当てたからといって、新しい値が他のスレッドに表示される保証はありません。コンパイラは、実際にメモリに書き出すのを延期する場合があります。この場合も、メモリバリアにより、保留中のすべてのメモリI/Oが「フラッシュ」されます。
もし私があなたなら、可能であれば、単純なロック/ミューテックス/モニター/クリティカルセクションよりも高いレベルの同期モデルを使用します。.NET言語やネイティブC++など、ほとんどの言語とプラットフォームで使用できるCSPライブラリがいくつかあります。
これにより、通常、競合状態とデッドロックを検出して修正するのが簡単になり、ばかげたレベルのスケーラビリティが可能になります。ただし、このパラダイムにもある程度のオーバーヘッドが伴うため、各スレッドの作業量は他の手法よりも少なくなる可能性があります。また、アプリケーション全体をこのパラダイム用に特別に構造化する必要があります(したがって、既存のコードに後付けするのは難しいですが、最初から始めるので問題は少なくなりますが、それでもなじみはありません)
別のアプローチはトランザクションメモリかもしれません。これは従来のプログラム構造に適合させるのが簡単ですが、いくつかの制限もあり、そのための多くの製品品質のライブラリを知りません(STM.NETが最近リリースされたので、チェックする価値があるかもしれません。IntelにはC++があります言語に組み込まれたSTM拡張機能を備えたコンパイラー)
ただし、どちらのアプローチを使用する場合でも、作業を独立したタスクに分割する方法と、スレッド間のクロストークを回避する方法について慎重に検討する必要があります。2つのスレッドが同じ変数にアクセスするときはいつでも、潜在的なバグがあります。また、2つのスレッドが同じ変数または同じアドレスの近くにある別の変数(たとえば、配列内の次または前の要素)にアクセスするときはいつでも、データをコア間で交換する必要があり、CPUキャッシュからメモリに強制的にフラッシュされます。 、次に他のコアのキャッシュに読み込みます。これは、パフォーマンスに大きな打撃を与える可能性があります。
ああ、 C ++でアプリケーションを作成する場合は、言語を過小評価しないでください。堅牢なコード、はるかに堅牢でないスレッドコードを記述できるようになる前に、言語を詳細に学習する必要があります。