単純なプログラムのライブラリを作成する場合、スレッドセーフにする方が費用効果が高いですか、それともマルチスレッドプログラムとASSERT()でのプログラムの使用を検出する方法、または(コンパイル時またはリンク時に)それを決定する方法がありますか?問題が発生する可能性があります。
この質問に関連するヘルプは、スレッドセーフに関する潜在的な問題を見つけるための自動化されたツールのサポート、それを強制するプログラミング言語機能、
スレッドセーフにするためのコスト(開発時間と労力の観点から)に依存します。考慮すべき事項は次のとおりです。
synchronized
キーワードやC#のlock
キーワードなど、効率や速度が重要な低レベルのスレッドプリミティブを処理する場合、困難な場合があります。また、ライブラリがマルチスレッド環境で使用される可能性と、使用される言語の規則によっても異なります。たとえば、Microsoftのオリジナル クラスライブラリの設計ガイドラインでは、非静的メンバーはスレッドセーフである必要はないと述べられています 。
いずれにせよ、最善のアプローチは、スレッドセーフであるものとそうでないものを明確に文書化することです。
ですから、これは図書館を利用している人々に警告するための投票だと思います。
はい、それはまさに私の卑劣なコメントでした。その費用を追加する正当な理由がない限り、それをしないでください。スレッドセーフは高価、設計者、開発者、テスター、そしてそれを必要としないユーザーにとってです。その費用を吸収する非常に正当な理由がない限り、あなたは時期尚早の最適化の罪を犯します。
Rand()
関数とほぼ同じくらい便利です。スレッドセーフは、それが理にかなっていて、それが必要であるために組み込まれています。それでも、どのように進めるかについて慎重に考える必要があります。
このようなもの(C#)がうまくいくかもしれません...
public class MyNonThreadSafeClass()
{
public MyNonThreadSafeClass()
{
currentThreadId = Thread.CurrentThread.ManagedThreadId;
}
private readonly int currentThreadId;
public void SomeNonThreadSafeMethod()
{
AssertSameThread();
//do your thing
}
private void AssertSameThread()
{
if(currentThreadId != Thread.CurrentThread.ManagedThreadId)
throw new InvalidOperationException("Method must be called on the same thread that created the containing object");
}
}
これにより、オブジェクトインスタンスを作成したスレッドのみがオブジェクトインスタンスを操作できるようになります。これのバリエーションにより、1つのメソッドが同時に異なるスレッドによって同時に呼び出されないようにする(ただし、1つのスレッドでインスタンスを作成し、それを別のスレッドに渡して処理できるようにする)か、作成スレッドにメッセージポンプが必要です。 (したがって、UIスレッドであるため、veryアプリの「メイン」スレッドである可能性があります)。
ただし、全体として、ライブラリがプロセスの並列スレッドによって使用されることを期待し、それをサポートしたい場合は、スレッドセーフにします。それほど難しいことではありません。モニター、ミューテックス、またはその他のロックを使用して共有状態を保護し、インスタンススコープの状態に依存しない「純粋関数」を優先します。
私が提案する最大のことは、クラスは、それを不適切に使用する呼び出し元との契約を無効と見なす必要があることですが、ある呼び出し元による不適切な使用は、他の呼び出し元との契約の有効性に影響を与えないはずです。
たとえば、クラスが「Popsicle Immunity」を実装し、IsFrozen
がtrueを返した場合、特定のプロパティの後続のすべての観測で同じ結果が得られると約束するとします。さらに、あるスレッドがインスタンスの「フリーズ」メソッドを呼び出し、別のスレッドがそのインスタンスを変更しているとします。オブジェクトを変更したり、Freeze
を呼び出したりするスレッドは、オブジェクトが何をするかについて正当な期待を持っていませんが、IsFrozen
を呼び出し、true
を返すことを確認し、他のいくつかを監視する他の場所のコードオブジェクトのプロパティは、後者のプロパティが決して変更されないことを期待する権利があります。前者のメソッドがオブジェクトを悪用したという事実は、不変であると主張するオブジェクトを期待する後者のコードの権利を弱めるべきではありません。