.Net 4.0并行编程-如何将数据写入并发集合?

发布于 2024-09-24 02:06:56 字数 278 浏览 0 评论 0 原文

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

我在这里遗漏了一些东西,还是没有“简单的方法”来使用这样的集合来做到这一点?

I have a grid which is defined as: List<List<Cell>>, where "Cell" is a custom class of mine.
My program has several threads which access various coordinates on the grid, and change data in the "Cell" class. But I only want one thread writing data to a "Cell" object at a time.
I thought using concurrent collections such as ConcurrentBag would be of service, but it seems that all the Concurrent Collections only have methods to ADD items or REMOVE them from the collection. There doesn't seem to be a thread-safe way to CHANGE data held within such a collection.

Am I missing something here, or is there no "easy way" to do it using such collections?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

微暖i 2024-10-01 02:06:56

您可以简单地使用互斥体来对单元格内容进行线程安全访问。它的工作原理如下:

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 了解更多详细信息。

You can simply use mutexes for thread-safe access to your cell contents. It works something like this:

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();
    }

   }

See http://msdn.microsoft.com/en-us/library/system.threading.mutex.aspx for more details.

怪我闹别瞎闹 2024-10-01 02:06:56

你读过这篇论文吗?

.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 对添加和更新的支持

Have you read this paper?

Thread-safe Collections in .NET Framework 4 and Their Performance Characteristics

Sample code using 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
}

You can also take a look at ConcurrentDictionary’s support for adding and updating.

心作怪 2024-10-01 02:06:56

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

您提到您将有很多读者,但只有一位作者。这是一个非常重要的细节。这意味着任何无锁同步策略都变得更加容易实现。然而,我不鼓励走这条路,因为它仍然很难走对路。但是,这也可能意味着 ReaderWriterLockSlim 可能性能更好。

您必须对两者进行试验,看看哪一种能够提供可维护性和效率的最佳平衡。我的预感是,尽管有多个读取器和一个写入器,但传统的会执行得更快,但它值得测试。当输入代码时,手指确实要容易得多。

这是两者的示例代码。

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();
    }
  }
}

The concurrent collections were intended as a means of safely modifying the collection itself; not the items. You will have to add your own synchronization primitives to the Cell class. If the outer and inner List instances themselves will remain unchanged there is no need to apply synchronization to them.

You mentioned that you will have many readers, but only one writer. That is an incredibly important detail. It means that any lock-free synchronization strategies become dramatically easier to implement. However, I do not encourage going down that route as it would still be quite difficult to get right. But, it could also mean that the ReaderWriterLockSlim might perform better than a lock.

You will have to experiment with both to see which one provides the best balance of maintainability and efficiency. My hunch is that you will find a traditional lock will perform faster despite having multiple readers and a single writer, but it is worth testing. It is certainly a lot easier on the fingers when typing out the code.

Here is sample code for both.

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.
    }    
  }
}

and

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();
    }
  }
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文