Static versus non-static lock object in synchroniz

2019-01-04 08:54发布

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?

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?

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

1条回答
The star\"
2楼-- · 2019-01-04 09:20

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

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()
  • thread 2 calls o1.foo(), will have to wait for thread 1 to finish
  • thread 3 calls o2.foo(), will also have to wait for thread 1 (and probably 2) to finish

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

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.

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.

查看更多
登录 后发表回答