2

我有一个网格,定义为:List<List<Cell>>,其中“Cell”是我的自定义类。我的程序有几个线程可以访问网格上的各种坐标,并更改“Cell”类中的数据。但我只希望一个线程一次将数据写入“Cell”对象。我认为使用 ConcurrentBag 等并发集合会有所帮助,但似乎所有并发集合都只有添加项目或从集合中删除项目的方法。似乎没有一种线程安全的方式来更改此类集合中保存的数据。

我在这里遗漏了什么,还是没有“简单的方法”来使用这样的集合?

4

3 回答 3

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 回答
2

你读过这篇论文吗?

.NET Framework 4 中的线程安全集合及其性能特征

示例代码使用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 回答
0

并发集合旨在作为安全修改集合本身的一种手段;不是项目。您必须将自己的同步原语添加到Cell类中。如果外部和内部List实例本身保持不变,则无需对它们应用同步。

你提到你会有很多读者,但只有一个作者。这是一个非常重要的细节。这意味着任何无锁同步策略都变得非常容易实现。但是,我不鼓励沿着这条路线走,因为它仍然很难做到正确。但是,这也可能意味着ReaderWriterLockSlim 可能lock.

您将不得不对两者进行试验,看看哪一个提供了可维护性和效率的最佳平衡。我的预感是,尽管有多个阅读器和一个编写器,您会发现传统的lock性能会更快,但值得测试。输入代码时,手指肯定要容易得多。

这是两者的示例代码。

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 回答