【问题标题】:Do static locks work across different children classes?静态锁是否适用于不同的子类?
【发布时间】:2012-03-01 04:04:12
【问题描述】:

如果我有

abstract class Parent
{
    static object staticLock = new object();

    public void Method1()
    {
        lock(staticLock)
        {
            Method2();
        }
    }

    protected abstract Method2();
}

class Child1 : Parent
{
    protected override Method2()
    {
          // Do something ...
    }
}

class Child2 : Parent
{
    protected override Method2()
    {
          // Do something else ...
    }
}

new Child1().Method1()new Child2().Method1() 的调用会使用相同的锁吗?

【问题讨论】:

  • 而staticLock是“私有的”(成员msdn.microsoft.com/en-us/library/ms173121.aspx的默认值),所以子类不能访问。
  • @AlexeiLevenkov 我只是想保证在任何时候都只调用一个Method2,我不需要子类来访问它。
  • @JohnSaunders:我没有关注你。这里的想法是有一个 不可覆盖public 方法,以确保 callers 总是获取锁。这样,派生类的作者就可以实现 Method2,而不必记住“哦,是的,我必须在这里锁定”。这种模式消除了一种错误,但当然也为另一种错误创造了机会;现在这些派生类的作者需要知道父类锁已被占用,并且不会导致死锁。
  • @AlexeiLevenkov:整个想法是防止派生类弄乱这个锁。不利的一面是,正如我在之前的评论中提到的,现在他们需要知道锁存在,以免导致死锁,即使他们无法访问锁。
  • 有道理。是的,正如大家所说。建议:您应该以一种不会使它看起来像 Method1 的兄弟(即 MethodImpl)的方式命名您的 Method2。

标签: c# .net inheritance static locking


【解决方案1】:

是的,一般来说,static 对象上的 lock 可以保护类的所有实例的数据。

来自MSDN

最佳实践是定义一个私有对象来锁定,或者一个私有的 静态对象变量,用于保护所有实例共有的数据

【讨论】:

    【解决方案2】:

    添加到 ken2k 的答案:[Yes] ... 除非它被标记为 [ThreadStatic](这显然不是这里的情况)。

    【讨论】:

    • 我不知道。对我正在处理的另一个问题非常重要。
    • 确实,线程静态锁宁愿破坏首先拥有锁的目的!
    【解决方案3】:

    是的。派生类不会从基类获取静态数据的副本。

    但是,generic 类并非如此。如果你说:

    class Base<T>
    {
        protected static object sync = new object();
        ...
    }
    
    class Derived1 : Base<int> { ... }
    class Derived2 : Base<int> { ... }
    class Derived3 : Base<string> { ... }
    class Derived4 : Base<string> { ... }
    class Derived5 : Base<object> { ... }
    class Derived6 : Base<object> { ... }
    

    Derived1 和 Derived2 的实例具有相同的同步对象。 Derived3 和 Derived4 的实例具有相同的同步对象。 Derived5 和 Derived6 的实例具有相同的同步对象。但是这三个同步对象都是不同的对象。

    【讨论】:

    • Eric,由于所有引用类型的泛型代码都被 jitted 一次,这是否意味着 class Derived4 : Base&lt;FileInfo&gt; { ... } 将与 Derived3 共享同一个同步对象?
    • @phoog:好问题。不;泛型类型的不同构造是不同的类型Base&lt;string&gt;Base&lt;FileInfo&gt; 是不同的类型,所以 Base&lt;string&gt;.syncBase&lt;FileInfo&gt;.sync 是不同的字段。事实上,作为一个实现细节,jitter 将 jit 一次 Base&lt;string&gt;Base&lt;FileInfo&gt;方法 并重新使用 jitted 状态并没有改变它们是 的事实不同的类型.
    • 感谢 Eric,Base&lt;string&gt;.syncBase&lt;FileInfo&gt;.sync 可能是同一个字段的想法相当令人不安。
    猜你喜欢
    • 1970-01-01
    • 2023-03-04
    • 2011-03-11
    • 2017-03-15
    • 1970-01-01
    • 2011-02-03
    • 1970-01-01
    • 2021-09-03
    • 1970-01-01
    相关资源
    最近更新 更多