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

[英]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?
  2. 对同步块使用静态锁定对象(代码A)和非静态锁定对象(代码B)有什么区别?

  3. How does it differ in practical applications?
  4. 它在实际应用中有何不同?

  5. What are the pitfalls one would have that the other wouldn't?
  6. 对方不会有什么陷阱?

  7. What are the criteria to determine which one to use?
  8. 确定使用哪一个的标准是什么?

Code A

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

Code 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.

我已经在这个问题中查看了答案,但不清楚不同的使用场景是什么。

1 个解决方案

#1


45  

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

区别很简单:如果锁定的对象在静态字段中,那么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.

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

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.

根据经验,您希望锁定对象具有与操作值相同的静态值。因此,如果仅操作非静态值,则需要非静态锁定对象。如果仅操作静态值,则需要静态锁定对象。

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. In those cases you might need a combination of static and non-static lock objects.

当您操纵静态和非静态值时,它将变得复杂。简单的方法是使用静态锁定对象,但这可能会增加synchronized块的大小,而不是绝对必要,并且可能需要比预期更多的锁争用。在这些情况下,您可能需要静态和非静态锁定对象的组合。

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.

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

智能推荐

注意!

本站翻译的文章,版权归属于本站,未经许可禁止转摘,转摘请注明本文地址:http://www.silva-art.net/blog/2013/08/21/67960869b39cd1878c73c0c30be026b7.html



 
© 2014-2019 ITdaan.com 粤ICP备14056181号  

赞助商广告