我有一个网格,定义为:List<List<Cell>>
,其中“Cell”是我的自定义类。我的程序有几个线程可以访问网格上的各种坐标,并更改“Cell”类中的数据。但我只希望一个线程一次将数据写入“Cell”对象。我认为使用 ConcurrentBag 等并发集合会有所帮助,但似乎所有并发集合都只有添加项目或从集合中删除项目的方法。似乎没有一种线程安全的方式来更改此类集合中保存的数据。
我在这里遗漏了什么,还是没有“简单的方法”来使用这样的集合?
我有一个网格,定义为:List<List<Cell>>
,其中“Cell”是我的自定义类。我的程序有几个线程可以访问网格上的各种坐标,并更改“Cell”类中的数据。但我只希望一个线程一次将数据写入“Cell”对象。我认为使用 ConcurrentBag 等并发集合会有所帮助,但似乎所有并发集合都只有添加项目或从集合中删除项目的方法。似乎没有一种线程安全的方式来更改此类集合中保存的数据。
我在这里遗漏了什么,还是没有“简单的方法”来使用这样的集合?
您可以简单地使用互斥锁对单元格内容进行线程安全访问。它的工作原理是这样的:
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 。
你读过这篇论文吗?
.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
}
并发集合旨在作为安全修改集合本身的一种手段;不是项目。您必须将自己的同步原语添加到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();
}
}
}