在jim mischel给出的关于实现线程安全树的答案中,他指出:
最简单的方法是用ReaderWriterLockSlim保护整个树。这允许多个读卡器并发访问或单个写入器独占访问。任何以任何方式修改结构的方法都必须获取写锁,并且在该线程释放写锁之前,不允许其他线程读取或写入该结构。
如果我没有错,这意味着树结构的方法/属性看起来像:
public class TreeNode
{
private String BackingData = "";
public String Data
{
get
{
lock (LockObject)
return BackingData;
}
set
{
lock (LockObject)
BackingData = value;
}
}
private TreeNode BackingParent { get; set; }
public TreeNode Parent
{
get
{
lock (LockObject)
return BackingParent;
}
}
//etc...
private List<TreeNode> BackingChildren { get; }
private Object LockObject { get; }
TreeNode()
{
BackingData = "";
BackingParent = null;
BackingChildren = new List<TreeNode>();
LockObject = new Object();
}
}
问题是,这并不是保护整个树——它甚至不保护树的单个节点,甚至只保护单个方法/属性。
这怎么能安排得让整棵树都受到保护呢?
我确实考虑过持有一个静态类,该类将根TreeNode映射到一个Object。然后,在这个静态类中有几个方法,它们使用Monitor方法根据根TreeNode进行锁定和解锁。监视器。IsEntered方法可以在TreeNode中使用,但要检查它是否已锁定,我们仍然需要走上未锁定的树来获取根TreeNode。即使在那时,如果IsEntered为false,我也不知道该如何处理。
是否有任何合适的方法来锁定一个对象,从而锁定该对象可能持有的所有子对象?
保护共享树节点引用的最简单方法是锁定全局共享的私有变量。这将使您达到螺纹安全方面所需的水平。这不是最有效的解决方案,因为整个树都被锁定了,但我怀疑这是否会引起任何担忧。
因此,每当您的任何函数触及全局根节点时,请确保您的
lock(mutex)
{
_root.Parent.Data = "Modified";
}
并且这将确保一次允许单个线程进入。