C# 多线程共享锁

发布于 2024-08-14 20:02:30 字数 800 浏览 4 评论 0原文

是否有一种通用方法可以在操作同一组数据的不同对象之间“共享”锁?

我知道通常不建议使用公共对象进行锁定。

例如,队列可以实现为线程安全的,但其他一些类可能需要特定的锁才能锁定多个队列操作。如果我有第三个类,它也需要在同一个 Queue 实例上进行多个锁定操作,会发生什么?

例如: (假设 L 是一个线程安全列表,只是为了节省一些输入)

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 条件之后,list 将不再包含该元素,因为 _lock 是私有对象。

我应该锁定实际的列表实例吗?

Is there a common way to "share" a lock between different objects operating on same set of data?

I am aware that having a public object for locking is usually not recommended.

For example, a Queue could be implemented as thread safe, but some other class might need a specific lock in order to lock several Queue operations. What happens if I have a third class, which also needs to make several locked operations on this same Queue instance?

For example:
(let's say that L<T> is a thread-safe list, just to save some typing)

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

If some other class, on a different thread, removes the old element just after the if condition, list will no longer contain the element, as _lock is a private object.

Should I lock on the actual list instance?

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

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

发布评论

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

评论(3

孤云独去闲 2024-08-21 20:02:30

不要将此列表公开为属性,仅公开与其交互的方法。然后,您可以处理一个类中的所有锁定,而不需要处理公共锁对象。

Don't expose this list as a property, only the methods to interact with it. Then you can handle all of the locking within the one class and not deal with a public lock object.

差↓一点笑了 2024-08-21 20:02:30

一种常见的方法是公开一个属性,例如 ICollection.SyncRoot 。当然,每个人都必须遵守锁才能使其正常工作。

如果您可以避免这种情况,并按照 ck 建议封装操作,那么这将更加健壮且易于理解。

A common way is to expose a property such as ICollection.SyncRoot. Of course, everyone has to obey the lock in order for this to work.

If you can possibly avoid this, and encapsulate the operations as ck suggests, that will be a lot more robust and easy to understand.

心凉怎暖 2024-08-21 20:02:30

从技术上讲,您可以轻松公开锁对象。问题是,建议不公开的真正原因是僵局。

如果锁定对象被公开,则会带来一些其他代码将锁定该对象而不考虑锁定顺序的风险。这反过来又可能导致僵局。

即使锁没有显式暴露,也存在同样的危险。

最好的方法是根本不公开锁——无论是隐式的还是显式的。换句话说,将它们完全埋藏在提供服务的类中。不幸的是,有时这不是一个选择。

Technically you can easily expose the lock object. The problem with this is that the real reason for the recommendation of not making them public is the deadlocks.

If the lock object is exposed it introduces the risk that some other code will lock on this object with no regard to the locking ordering. This in turn can lead to deadlocks.

The same danger exists even if the locks are not exposed explicitly.

The best approach is not to expose the locks at all - neither implicitly nor explicitly. In other words bury them completely inside the class providing services. Unfortunately sometimes this is not an option.

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