web-dev-qa-db-ja.com

複数のスレッドで使用される変数をロックする方法

ここでひどく質問しました 複数のスレッドで変数をロックします わかりやすくするために、ここで質問します。正しく質問できることを願っています。

classA
  creates instance of classB
  has methodA that can update & uses classB's myVar
  has methodB that can update & uses classB's myVar

classB
  has a variable myVar

methodAとmethodBは両方とも別々のスレッドで実行できます(mainからの新しいスレッドで呼び出されます)。これがスレッドセーフであることを確認するにはどうすればよいですか?

15
SimpleOne

lockキーワードを使用して、複数のスレッドで同時に実行できるコードを保護します。

public class ClassA
{
  private ClassB b = new ClassB();

  public void MethodA()
  {
    lock (b)
    {
      // Do anything you want with b here.
    }
  }

  public void MethodB()
  {
    lock (b)
    {
      // Do anything you want with b here.
    }
  }
}

lockは、ステートメントで使用されるオブジェクトインスタンスを保護またはロックしないことに注意することが重要です。代わりに、オブジェクトは、同じオブジェクトインスタンスを使用する別のセクションがすでに実行されている場合に実行を防止する必要があるコードのセクションを識別する方法として使用されます。つまり、lockステートメントで任意のオブジェクトインスタンスを使用でき、それでもClassBのメンバーにアクセスしても安全です。

21
Brian Gideon

ブログ投稿 複数のスレッドにリストに値を追加させ、 lock() を使用して、書き込みが衝突しないようにすることと、これを行う必要がある理由について記述しました。

3
Erik Noren

最も簡単な解決策:ClassBのインスタンスをスレッド間で共有しないでください。

つまり、スレッド宣言を使用して新しいClassBをインスタンス化し、パラメーターとして送信します。

0
Austin Salonen

残念ながら、スレッドセーフの観点から何が成功と見なされるかについての質問はややあいまいです。スレッドセーフとは、複数のスレッドが実行されている場合に操作が正しく機能することを意味します。

欠落しているように見えるのは、classA.methodA(...)またはclassA.methodB(...)を呼び出す別のスレッドの前に、classA.methodAまたはclassA.methodBがclassB.myVarで操作を終了する必要があるかどうかです。それはあなたが必要とするであろうロックパターンのタイプを決定するでしょう。

たとえば、値の読み取りを保証する必要がある場合は、次のようになります。

public class classA
{
    private classB b = new classB();

    public void methodA()
    {
        lock (b)
        {
            // Operation without calling methodA() or methodB() 
            // Read b.myVar
            // Update b.myVar
        }
    }

    public void methodB()
    {
        lock (b)
        {
            // Operation without calling methodA() or methodB()
            // Read b.myVar
            // Update b.myVar
        }
    }
}

別の例では、b.myVarがキャッシュのように同期する必要があるコレクションのタイプである場合、次のようになります。

public class classA
{
    private classB b = new classB();

    public void methodA()
    {
        // Read b.myVar for missing collection item

        lock (b)
        {
            // Check for missing collection item again. If not missing, leave lock
            // Operation without calling methodA() or methodB() 
            // Read b.myVar
            // Update b.myVar with new array item
        }
    }

    public void methodB()
    {
        // Read b.myVar for missing collection item
        lock (b)
        {
            // Check for missing collection item again. If not missing, leave lock
            // Operation without calling methodA() or methodB() 
            // Read b.myVar
            // Update b.myVar with new array item
        }
    }
}
0
Frank Liao

lock ステートメントのドキュメントを確認してください。

0
Kon

ClassBは変数を公開するべきではありません(おそらくデータメンバーを意味します)。代わりに、プロパティまたはメソッドのセットを公開し、 ReaderWriterLockSlim を使用して複数のスレッドを処理します。

0
user203570