Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

wait() does not free all current locks, how it can be done?

According to Java doc, when obj1.wait() happens, "The thread releases ownership of this monitor and waits until another thread notifies..."

So, the lock of obj1 is freed, while the current thread is waiting. But what about all other locks? It is possible, that the piece of the code is locking two objects:

synchronized(obj2){
    f1();
    synchronized(obj1){
        f2();
        obj1.wait();
    }
}

Obj2 won't be freed, but the thread does not run, another thread will wait for freeing of obj2 in vain... I don't understand the reason of that continuing locking of obj2. But OK, it is as it is.

But how can I organize this waiting better, how can I unlock for the time of waiting all or at least several current locks?

like image 955
Gangnus Avatar asked Oct 19 '25 02:10

Gangnus


1 Answers

You could use Locks and Conditions which are more flexible than sychronized statements.

For your example you could replace obj2 with a ReentrantLock:

Lock lock2 = new ReentrantLock();

try {
    // Blocks until the lock is acquired, just like a `synchronized` statement
    lock2.lock();
    f1();

    synchronized (obj1) {
        f2();
        lock2.unlock();
        obj1.wait();
        lock2.lock();
    }
}
// Use `finally` to make sure the lock is always released, even if an exception is thrown
finally {
    // Exception might have been thrown before current thread could acquire lock again, cannot 
    // unlock then
    if (lock2.isHeldByCurrentThread()) {
        lock2.unlock();
    }
}

However, this would allow another thread to acquire lock2 before the current thread starting waiting for obj1. If this is not desired you could replace obj1 with a Lock instead and wait for obj2.

like image 119
Marcono1234 Avatar answered Oct 20 '25 15:10

Marcono1234