Java 同步块中的静态与非静态锁定对象

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/18356795/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-12 00:50:58  来源:igfitidea点击:

Static versus non-static lock object in synchronized block

javastaticsynchronizationlockingsynchronized

提问by ADTC

Trying to visualize and understand synchronization.

尝试可视化和理解同步

  1. What are the differences between using a static lock object(code A)and a non-static lock object(code B)for a synchronized block?
  2. How does it differ in practical applications?
  3. What are the pitfalls one would have that the other wouldn't?
  4. What are the criteria to determine which one to use?
  1. 同步块使用静态锁对象(代码 A)非静态锁对象(代码 B)有什么区别?
  2. 它在实际应用中有何不同?
  3. 一个人会遇到哪些其他人不会的陷阱?
  4. 决定使用哪一个的标准是什么?

Code A

代码 A

public class MyClass1 {
  private static final Object lock = new Object();
  public MyClass1() {
    //unsync
    synchronized(lock) {
      //sync
    }
    //unsync
  }
}

Code B

代码 B

public class MyClass2 {
  private final Object lock = new Object();
  public MyClass2() {
    //unsync
    synchronized(lock) {
      //sync
    }
    //unsync
  }
}

Note

笔记

The above code shows constructors, but you could talk about how the behavior is different in a static method and a non-static method too. Also, would it be advantageous to use a static lock when the synchronized block is modifying a static member variable?

上面的代码显示了构造函数,但您也可以讨论静态方法和非静态方法的行为有何不同。另外,当同步块修改静态成员变量时,使用静态锁是否有利?

I already looked at answers in this question, but it's not clear enough what the different usage scenarios are.

我已经看过这个问题的答案,但还不够清楚不同的使用场景是什么。

采纳答案by Joachim Sauer

The difference is simple: if the locked-on object is in a staticfield, then all instances of MyClass*will sharethat lock (i.e. no two objects will be able to lock on that object at the same time).

区别很简单:如果锁定的对象在一个static字段中,那么 的所有实例都MyClass*共享该锁(即,没有两个对象能够同时锁定该对象)。

If the field is non-static, then each instance will have its own lock, so only calls of the method on the same objectwill lock each other.

如果字段是非静态的,那么每个实例都会有自己的锁,所以只有对同一对象的方法调用才会互相锁住。

When you use a static lock object:

当您使用静态锁对象时:

  • thread 1 calls o1.foo()
  • thread 2 calls o1.foo(), will have to wait for thread 1 to finish
  • thread 3 calls o2.foo(), will alsohave to wait for thread 1 (and probably 2) to finish
  • 线程 1 调用 o1.foo()
  • 线程 2 调用o1.foo(),必须等待线程 1 完成
  • 线程 3 调用o2.foo()必须等待线程 1(可能还有 2)完成

When you use a non-static lock object:

当您使用非静态锁对象时:

  • thread 1 calls o1.foo()
  • thread 2 calls o1.foo(), will have to wait for thread 1 to finish
  • thread 3 calls o2.foo(), it can just continue, not minding thread 1 and 2
  • 线程 1 调用 o1.foo()
  • 线程 2 调用o1.foo(),必须等待线程 1 完成
  • 线程 3 调用o2.foo(),它可以继续,不介意线程 1 和 2

Which one of those you'll need depends on what kind of data you try to protectwith your synchronized block.

您需要哪一种取决于您尝试使用同步块保护的数据类型。

As a rule of thumb, you want the lock-object to have the same static-ness than the operated-on value. So if you manipulate non-static values only, you'll want a non-static lock object. If you manipulate static values only, you'll want a static lock object.

根据经验,您希望锁定对象static与操作值具有相同的-ness。所以,如果你处理非静态值,你会想要一个非静态锁定对象。如果您操作静态值,您将需要一个静态锁对象。

When you manipulate static and non-staticvalues, then it'll become complicated. The easyway would be to just use a static lock object, but that might increase the size of the synchronized-block more than absolutely necessary and might need to more lock contention than desired. In those cases you might need a combination of static and non-static lock objects.

当您操作静态和非静态值时,它会变得复杂。在简单的方法是只使用一个静态的锁定对象,但比预期的可能增加同步块的大小超过绝对必要的,可能需要更多的锁争用。在这些情况下,您可能需要静态和非静态锁定对象的组合。

In your particular case you use the lock in the constructor, which will only ever be executed once per instance, so a non-static lock-object doesn't make any sense here.

在您的特定情况下,您在构造函数中使用锁,每个实例只会执行一次,因此非静态锁对象在这里没有任何意义。