看网上的文章都说lock的对象要是私有的。但是我看了下ICollection里的syncroot是public的。list,queue都实现了这个syncroot,是不是有矛盾。其实我想实现这样一个功能,有一个实例对象A,我想在不同的线程中锁定这个对象不让其他线程修改。我的想法是在这个对象所在的类里,定义一个锁(比如名字叫lock),在不同的线程中,只要lock(A.lock)就可以实现了。但是lock的对象不能是public的,那我们如果我在类中定义这个lock,就必须声明未public的才能通过A.lock拿到。如果不在类里面定义把这个lock变量跟类封装到一起,难道我每声明一个类的实例,就在下面再声明一个private object, 如果我有10个实例对象在不同的线程中要做互斥,那么我外面要再声明10个 private ojbect么。

解决方案 »

  1.   

    特意去翻了一下源码,
    List<T> 、Queue<T>这些类的SyncRoot都是私有的,定义如下:[NonSerialized]
    private object _syncRoot;
    [__DynamicallyInvokable]
    object ICollection.SyncRoot
    {
        [__DynamicallyInvokable] get
        {
        if (this._syncRoot == null)
            Interlocked.CompareExchange<object>(ref this._syncRoot, new object(), (object) null);
        return this._syncRoot;
        }
    }
    不知道你说public的结论怎么来的
      

  2.   

    另外,按你说的需求,
    你的这个实例对象A,它从属于哪个对象,就应该由哪个对象负责它的修改操作(含线程安全保障),简单示例:
    public class xxx{
    private object a;
    public object A{get{return a;}set{lock (a){// 对a进行操作}}}
    }
      

  3.   

    是我理解的问题,我看_syncRoot是私有的,但是在使用的时候用的是SyncRoot,是公有的属性,否则不会被list.SyncRoot能访问到,但是这个属性只有get没有set,所以这个角度说应该还是私有的。 不知道这样理解是不是对的。
      

  4.   

    你没看我贴的代码?
    object ICollection.SyncRoot
    这个没有修饰符,表示private,并不是public
      

  5.   

    明显你在网上看的文章有毒啦。。M$ 都已经以身作则把 SyncRoot 公开出来了,那样就是从设计原则上是没有问题的。。
    当然,你要觉得 M$ 的技术大牛,框架师等等水平比不上那些网文的作者。。那也无话可说。。附,lock(A.Lock) 是多余的,在大多数情况只直接 lock(A) 即可。
      

  6.   

    特意创建了一个 .Net Framework4.6.1的项目测试了一下,用实例加点,联想不出来:
      

  7.   

    直接加点不行,要加上(ICollection)修饰aa是可以的,我现在也是这么用的。 只是说之前是list,.net已经写好了可以直接用syncroot,我现在有自定义的一个类,也想这样用。
      

  8.   

    哦哦,SyncRoot这个属性是显式接口实现,必须通过接口才能访问,可以在外部锁定它,避免数组操作的线程不安全性,
    参考MSDN:
    https://docs.microsoft.com/zh-cn/dotnet/api/system.collections.icollection.syncroot?redirectedfrom=MSDN&view=netframework-4.7.2#System_Collections_ICollection_SyncRoot要看你的具体业务场景,我还是建议,在对象内部封装掉线程安全操作,不要在外部到处去lock
      

  9.   

    有一个实例对象A,我想在不同的线程中锁定这个对象不让其他线程修改。
    这个 A 是在哪里实例化的?由于作用域的关系,并不存在全局对象如果你到处实例化A的话,lock(A.lock)就根本起不到锁定的作用
    因此 A.lock 只能是 A 类型的公共的静态属性,自然我就可以在 B.Func() 中 A.lock = null; 来让你的锁定不能得以实现
    这就是 lock的对象要是私有的 的原因(定义在本类中也一样)
      

  10.   

    在 WPF 的输入层,有一点地方的线程锁的对象是公开的,只是为了多个类之间公用相同的对象防止线程同步问题具体请看 WPF 触摸到事件
    https://lindexi.gitee.io/post/WPF-%E8%A7%A6%E6%91%B8%E5%88%B0%E4%BA%8B%E4%BB%B6.html