【问题标题】:Static members need special synchronization blocks?静态成员需要特殊的同步块吗?
【发布时间】:2008-11-24 16:09:47
【问题描述】:

我有一个看起来像这样的类:

public class Test {

private static final Object someObject = new Object();

public void doSomething()
{
    synchronized (someObject) {
        System.out.println(someObject.toString());
    }
}

}

我可以认为对象是同步的,还是因为它是静态成员有问题?

编辑:请注意,不同的线程可能正在访问 doSomething(),并且在这种情况下必须以线程安全的方式访问对象。

【问题讨论】:

    标签: java static synchronization locking


    【解决方案1】:

    通过使用静态对象作为监视器对象,只有一个使用任何 Test 类实例的线程可以进入同步块。如果监视器对象不是静态对象,则其他持有不同 Test 类实例的线程可能会进入同步块。

    【讨论】:

    • 我不明白。这是否意味着代码 sn-p 像我预期的那样工作?
    • 我相信 David 的观点是,通过将其设为静态成员,如果预计会有很多线程调用该方法,则会引入瓶颈的可能性。
    【解决方案2】:

    这里 someObject 充当了对 Test 类型的 所有 对象的锁(监视器)。也就是说,如果在两个单独的 Test 实例上调用 doSomething(),则一个将在另一个完成之前阻塞。这与同步方法不同,同步方法主要等同于上面的代码,将 someObject 替换为 this

    someObject 更改为非静态将导致每个实例锁定。这本质上是 Effective Java 的第 70 项中描述的“私有锁定对象”习语。

    【讨论】:

      【解决方案3】:

      像这样获取特定于类的独立于实例的锁的常见模式是使用 Class 对象本身:

      public class Test {
        public void doSomething() {
          synchronized (Test.class) {
            // something
          }
        }
      }
      

      这实际上是同步静态方法所做的。当然,如果您想要多个这样的锁,则需要像示例中一样将它们声明为静态字段。

      【讨论】:

        【解决方案4】:

        如果使用不同的类加载器加载测试类会发生什么?

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 2016-09-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2012-03-14
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多