2

いくつかの配列リストを含むクラスがあります。

私のメインクラスは、このクラスの新しいインスタンスを作成します。私のメインクラスには、配列リストを含むクラスに追加および削除するスレッドが少なくとも2つあります。現時点ではすべてが正常に実行されていますが、配列リストを含むクラスを揮発性として宣言する方が安全かどうか疑問に思っていました。

private volatile myclass;
myclass = new myclass();
......
myclass.Add(...)
myclass.Clear(..)
4

2 に答える 2

4

この例では、volatileキーワードを使用しても、コードはスレッドセーフになりません。volatileキーワードは通常、変数(つまり、クラスフィールド)の値を読み書きするときに、その変数の最新の値がキャッシュから読み取られるのではなく、メインメモリから読み取られるか、メインメモリに直接書き込まれるようにするために使用されます(例:たとえば、CPUレジスタ)。volatileキーワードは、「この共有フィールドでキャッシュの最適化を使用しない」という言い方であり、スレッドがフィールドのローカルコピーを使用する可能性があるため、互いの更新が表示されないという問題を取り除きます。

あなたの場合、myclassの値は実際には更新されていない(つまり、myclassを再割り当てしていない)ので、volatileは役に立ちません。また、これで実際にスレッドセーフにしたいmyclass変数の更新ではありません。とにかくケース。

実際のクラスの更新をスレッドセーフにしたい場合は、「追加」と「クリア」の周りに「ロック」を使用するのが簡単な方法です。これにより、一度に1つのスレッドのみがこれらの操作(myclassの内部状態を更新する)を実行できるようになるため、並行して実行しないでください。

ロックは次のように使用できます。

private readonly object syncObj = new object(); 
private readonly myclass = new myclass();
......

lock (syncObj)
{
    myclass.Add(...)
}

lock (syncObj)
{
    myclass.Clear(..)
}

また、サンプルコードには表示されていませんが、「追加」によって更新されている状態を読み取るコードの周囲にロックを追加する必要があります。

マルチスレッドコードを最初に作成するとき、コレクションに追加するときにロックが必要になる理由が明確でない場合があります。ListまたはArrayListを例にとると、これらのコレクションは内部的に配列をバッキングストアとして使用し、この配列を動的に「成長」させるため(つまり、新しいより大きな配列を作成し、古いコンテンツをコピーすることによって)、問題が発生します。 Addが呼び出されると、容量が満たされます。これはすべて内部で発生し、この配列と、コレクションの現在のサイズなどの変数(実際の配列の長さではなく)を維持する必要があります。したがって、内部アレイを拡張する必要がある場合、コレクションへの追加には複数のステップが含まれる場合があります。安全でない方法で複数のスレッドを使用する場合、複数のスレッドを追加すると、間接的に成長が発生する可能性があります。したがって、お互いの更新を踏みにじります。複数のスレッドが同時に追加される問題だけでなく、別のスレッドがコレクションを読み取ろうとしている可能性があるという問題もあります。内部状態が変更されている間。ロックを使用すると、他のスレッドからの干渉なしにこれらの操作が確実に実行されます。

于 2010-07-28T08:11:45.760 に答える
2

現在、コードは間違っています。キーワードを追加してvolatileも修正されません。同期を追加せずにスレッド間で.NETクラスを使用することは安全ではありません。

コードの構造について詳しく知らなければ、簡単なアドバイスをするのは難しいです。最初のステップはlock、リストオブジェクトへのすべてのアクセスでキーワードの使用を開始することです。ただし、コードには、複数のスレッド間で機能しない仮定が存在する可能性があります。

マルチスレッドアクセスに対してすでに安全なコレクションクラスを使用することは可能です。これによりlock、適切な場所でキーワードを取得する必要がなくなりますが、エラーが発生する可能性があります。

コードをもう少し投稿できますか?そうすれば、スレッドセーフにするためのより具体的な提案をすることができます。

于 2010-07-28T08:05:21.967 に答える