If I have a class that has 2 methods say setA
and setB
that have synchronized
but they are not synchronized on the same object, how do I lock it such that if there were two instances of the class, methods setA
and setB
cannot happen simultaneously?

- 55
- 6
-
Create a static object and synchronize on that. – Thorbjørn Ravn Andersen Mar 20 '16 at 19:24
-
The question is a bit ambiguous. If you have obj1 and obj2, do you want calls `obj1.setA()` to block `obj2.setA()` or just block `obj1.setB()`? – Gray May 25 '16 at 01:21
4 Answers
In short, you can use a synchronized (lockObj) {...}
block in the body of both methods, and use the same lockObj
instance.
class MyClass {
private final Object lock;
public MyClass(Object lock) {
this.lock = lock;
}
public void setA() {
synchronized (lock) {
//...
}
}
public void setB() {
synchronized (lock) {
//...
}
}
}
Few things to note:
- The lock needs not to be static. It is up to your implementation how you provide it. But every
MyClass
instance must use the same lock instance if you want them to prevent threads from executing their blocks simultaneously. - You can not use synchronized methods in this case, since each non static
synchronized
method will use its on this instance's monitor. - If you want to access other instance members, you can not use
static synchronized
methods either.

- 790
- 6
- 8
You can still synchronize on another object within the class that you create.
Object lock = new Object();
Then just synchronize on the lock object.
If you want to get a bit more into it you can use the util.concurrency libraries. Check out Semaphores or Latches, depends on what you want to do with your setA and setB

- 110
- 9
Synchronize them on a single, static reference. A private static final Object lock = new Object ()
will do, as Will just TheClass.class.
This will also mean that no two threads can invoke setA at the same time, even if nobody is invoking setB. If that's not acceptable, you can use a (static) read-write lock for finer-grained access. setA uses the read lock, and setB uses the write lock; that means that any number of threads can invoke setA, but only one can invoke setB. You probably don't want the reverse to also be true, because that's susceptible to deadlocking.

- 42,327
- 7
- 87
- 124
Multiple ways.
1) You can synchronize the methods: public synchronized void setA()
Doing that means that only one thread can enter the method at a time (good and bad)
2) A better solution would be to use a ReentrantLock
:
ReentrantLock lock = new ReentrantLock();
void public void setA() {
lock.lock();
try {
//Do Something
}
finally {
lock.unlock();
}
}
There are other ways as well. You can check the Java tutorial on concurrency: https://docs.oracle.com/javase/tutorial/essential/concurrency/locksync.html
Another decent posting: http://winterbe.com/posts/2015/04/30/java8-concurrency-tutorial-synchronized-locks-examples/
Good luck!

- 7,709
- 4
- 36
- 51