导航
  • 主页
  • C#综合技术
  • C#互联网桌面应用
  • AppLauncher
  • WinForm
  • WPF
  • 问答

为什么syncroot是public的,lock不是最好要lock private的吗

suncs2001 2018-10-09 04:13:24
看网上的文章都说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么。
...全文
520 点赞 收藏 15
写回复
15 条回复
切换为时间正序
请发表友善的回复…
发表回复
suncs2001 2020-04-25
这个问题我理解所谓的是私有目的可能是不让别人修改。虽然点出来是public的,但是通过属性设置器的,实际只公布了一个get方法,没有公布set方法,所以还是不能修改。相当于还是私有的。
回复
lindexi_gd 2018-10-14
在 WPF 的输入层,有一点地方的线程锁的对象是公开的,只是为了多个类之间公用相同的对象防止线程同步问题 具体请看 WPF 触摸到事件 https://lindexi.gitee.io/post/WPF-%E8%A7%A6%E6%91%B8%E5%88%B0%E4%BA%8B%E4%BB%B6.html
回复
xuzuning 2018-10-12
有一个实例对象A,我想在不同的线程中锁定这个对象不让其他线程修改。
这个 A 是在哪里实例化的?由于作用域的关系,并不存在全局对象

如果你到处实例化A的话,lock(A.lock)就根本起不到锁定的作用
因此 A.lock 只能是 A 类型的公共的静态属性,自然我就可以在 B.Func() 中 A.lock = null; 来让你的锁定不能得以实现
这就是 lock的对象要是私有的 的原因(定义在本类中也一样)
回复
学习一下,希望有用处
回复
qq_18880339 2018-10-11
支持 支持,很实用的东西 非常实用
回复
水边2 2018-10-10
哦哦,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
回复
suncs2001 2018-10-10
直接加点不行,要加上(ICollection)修饰aa是可以的,我现在也是这么用的。 只是说之前是list,.net已经写好了可以直接用syncroot,我现在有自定义的一个类,也想这样用。

回复
水边2 2018-10-10
回复
水边2 2018-10-10
引用 6 楼 suncs2001 的回复:
如果私有的,为什么用实例可以加点可以联想出来,私有的应该不可以直接访问才对。
特意创建了一个 .Net Framework4.6.1的项目测试了一下,用实例加点,联想不出来:
回复
suncs2001 2018-10-10
引用 4 楼 youbl 的回复:
你没看我贴的代码?
object ICollection.SyncRoot
这个没有修饰符,表示private,并不是public


如果私有的,为什么用实例可以加点可以联想出来,私有的应该不可以直接访问才对。
回复
CGabriel 2018-10-09
明显你在网上看的文章有毒啦。。 M$ 都已经以身作则把 SyncRoot 公开出来了,那样就是从设计原则上是没有问题的。。 当然,你要觉得 M$ 的技术大牛,框架师等等水平比不上那些网文的作者。。那也无话可说。。 附,lock(A.Lock) 是多余的,在大多数情况只直接 lock(A) 即可。
回复
水边2 2018-10-09
你没看我贴的代码? object ICollection.SyncRoot 这个没有修饰符,表示private,并不是public
回复
suncs2001 2018-10-09
是我理解的问题,我看_syncRoot是私有的,但是在使用的时候用的是SyncRoot,是公有的属性,否则不会被list.SyncRoot能访问到,但是这个属性只有get没有set,所以这个角度说应该还是私有的。 不知道这样理解是不是对的。


回复
水边2 2018-10-09
另外,按你说的需求, 你的这个实例对象A,它从属于哪个对象,就应该由哪个对象负责它的修改操作(含线程安全保障),简单示例:


public class xxx{
private object a;
public object A{get{return a;}set{lock (a){// 对a进行操作}}}
}

回复
水边2 2018-10-09
特意去翻了一下源码, 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的结论怎么来的
回复
发动态
发帖子
C#
创建于2007-09-28

10.4w+

社区成员

.NET技术 C#
申请成为版主
社区公告

全世界最好的语言,没有之一.