在同一组数据上运行的不同对象之间是否存在“共享”锁定的常用方法?
我知道通常不建议使用公共对象进行锁定。
例如,Queue可以实现为线程安全,但是其他一些类可能需要特定的锁才能锁定多个Queue操作。如果我有第三个类,还需要在同一个Queue实例上进行多次锁定操作,会发生什么?
例如:
(假设L<T>
是一个线程安全的列表,只是为了节省一些打字)
class Worker
{
private readonly L<Something> _list;
public Worker(L<Something> list) { _list = list; }
private readonly object _lock = new object();
public void Replace(Something old, Something new)
{
lock (_lock)
{
if (_list.Contains(old))
{
_list.Remove(old);
_list.Add(new);
}
}
}
}
如果某个其他类在另一个线程上删除了old
条件之后的if
元素,则列表将不再包含该元素,因为_lock
是一个私有对象。
我应该锁定实际的列表实例吗?
答案 0 :(得分:10)
不要将此列表公开为属性,只显示与其交互的方法。然后,您可以处理一个类中的所有锁定,而不处理公共锁定对象。
答案 1 :(得分:9)
常见的方法是公开ICollection.SyncRoot等属性。当然,每个人必须服从锁才能使其发挥作用。
如果您可以避免这种情况,并将操作封装为ck建议,那将更加强大且易于理解。
答案 2 :(得分:5)
从技术上讲,您可以轻松地公开锁定对象。这样做的问题是建议不将它们公开的真正原因是僵局。
如果锁定对象被暴露,则会引入一些其他代码将锁定此对象而不考虑锁定顺序的风险。这反过来会导致死锁。
即使没有明确暴露锁,也存在同样的危险。
最好的方法是不要公开锁 - 既不是隐式也不是显式。换句话说,将它们完全埋在提供服务的课程中。不幸的是,有时这不是一个选择。