2

次のように定義されたグリッドがありますList<List<Cell>>。「セル」は私のカスタムクラスです。私のプログラムには、グリッド上のさまざまな座標にアクセスし、「Cell」クラスのデータを変更するスレッドがいくつかあります。しかし、一度に「Cell」オブジェクトにデータを書き込むスレッドは 1 つだけです。ConcurrentBag などの並行コレクションを使用すると役立つと思いましたが、すべての並行コレクションにはアイテムを追加するか、コレクションからアイテムを削除するメソッドしかないようです。そのようなコレクション内に保持されているデータを変更するためのスレッドセーフな方法はないようです。

ここで何か不足していますか、またはそのようなコレクションを使用してそれを行う「簡単な方法」はありませんか?

4

3 に答える 3

2

この論文を読んだことがありますか?

.NETFramework4のスレッドセーフコレクションとそのパフォーマンス特性

を使用したサンプルコードConcurrentBag

if (bag.TryTake(out node))
{
    for (int i = 0; i < node.Children.Count; i++)
    {
        bag.Add(node.Children[i]);
    }

    ProcessNode(node); //e.g. a short string comparison
}

の追加と更新に対するConcurrentDictionaryのサポートも確認できます。

于 2010-09-17T19:43:41.473 に答える
2

セルの内容へのスレッドセーフなアクセスには、単純にミューテックスを使用できます。次のように機能します。

class Cell{

 private static Mutex mut = new Mutex();

    private static void SetResource(...)
    {
        // Wait until it is safe to enter.
        mut.WaitOne();

        //change cell contents here...

        // Release the Mutex.
        mut.ReleaseMutex();
    }

   }

詳細については、 http://msdn.microsoft.com/en-us/library/system.threading.mutex.aspxを参照してください。

于 2010-09-17T18:33:56.097 に答える
0

並行コレクションは、コレクション自体を安全に変更する手段として意図されていました。アイテムではありません。独自の同期プリミティブをCellクラスに追加する必要があります。外部インスタンスと内部Listインスタンス自体が変更されない場合は、それらに同期を適用する必要はありません。

あなたは多くの読者を持つことになると言いましたが、書き手は 1 人だけです。それは信じられないほど重要な詳細です。これは、ロックのない同期戦略の実装が劇的に容易になることを意味します。ただし、正しい道をたどるのはまだかなり難しいので、その道をたどることはお勧めしません。ただし、が よりも優れたパフォーマンスを発揮するReaderWriterLockSlim 可能性があることも意味しlockます。

どちらが保守性と効率性の最適なバランスを提供するかを確認するには、両方を試してみる必要があります。lock複数のリーダーと 1 つのライターを使用する場合でも、従来型の方が高速に動作することがわかると思いますが、テストする価値はあります。コードを入力するときは、確かに指がはるかに簡単です。

両方のサンプル コードを次に示します。

public class Cell
{
  private object m_LockObject = new object();

  public object ReadMyState()
  {
    lock (m_LockObject)
    {
      // Return the data here.
    }    
  }

  public void ChangeMyState()
  {
    lock (m_LockObject)
    {
      // Make your changes here.
    }    
  }
}

public class Cell
{
  private ReaderWriterLockSlim m_LockObject = new ReaderWriterLockSlim();

  public object ReadMyState()
  {
    m_LockObject.EnterReadLock();
    try
    {
      // Return the data here.
    }
    finally
    {
      m_LockObject.ExitReadLock();
    }
  }

  public void ChangeMyState()
  {
    m_LockObject.EnterWriteLock();
    try
    {
      // Make your changes here.
    }
    finally
    {
      m_LockObject.ExitWriteLock();
    }
  }
}
于 2010-09-17T20:39:54.613 に答える