Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
176 views
in Technique[技术] by (71.8m points)

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

Question&Answers:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

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.


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...