简体   繁体   English

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

[英]Static versus non-static lock object in synchronized block

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 ? 同步块使用静态锁定对象 (代码A)非静态锁定对象 (代码B)有什么区别?
  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? 确定使用哪一个的标准是什么?

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? 另外,当synchronized块修改静态成员变量时,使用静态锁是否有利?

I already looked at answers in this question , but it's not clear enough what the different usage scenarios are. 我已经在这个问题中查看了答案,但不清楚不同的使用场景是什么。

The difference is simple: if the locked-on object is in a static field, then all instances of MyClass* will share that lock (ie 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 object will lock each other. 如果该字段是非静态的,则每个实例都有自己的锁,因此只有对同一对象的方法调用才会相互锁定。

When you use a static lock object: 使用静态锁定对象时:

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

When you use a non-static lock object: 使用非静态锁定对象时:

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

Which one of those you'll need depends on what kind of data you try to protect with your synchronized block. 您需要哪一个取决于您尝试使用synchronized块保护的数据类型。

As a rule of thumb, you want the lock-object to have the same static -ness than the operated-on value. 根据经验,您希望锁定对象具有与操作值相同的static 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. 如果操作静态值,则需要静态锁定对象。

When you manipulate static and non-static values, then it'll become complicated. 当您操纵静态和非静态值时,它将变得复杂。 The easy way 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. 简单的方法是使用静态锁定对象,但这可能会增加synchronized块的大小,而不是绝对必要,并且可能需要比预期更多的锁争用。 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. 在您的特定情况下,您在构造函数中使用了锁,每个实例只执行一次,因此非静态锁对象在这里没有任何意义。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM