In general you should use higher-level concurrency utilities when possible.
However, if none of the higher-level constructs work in your case, the direct
replacement is to use a
ReentrantLock and a single
Condition
on that lock.
For example, if your Java code was something like:
private Object lock = new Object();
...
synchronized(lock) {
...
lock.wait();
...
lock.notify();
...
lock.notifyAll();
...
}
You can change it to the following Kotlin:
private val lock = ReentrantLock()
private val condition = lock.newCondition()
lock.withLock { // like synchronized(lock)
...
condition.await() // like wait()
...
condition.signal() // like notify()
...
condition.signalAll() // like notifyAll()
...
}
While this is slightly more verbose, conditions do provide some extra
flexibility, as you can have multiple conditions on a single lock, and there
are also other kinds of locks (notably ReentrantReadWriteLock.ReadLock and
ReentrantReadWriteLock.WriteLock).
Note that withLock is a Kotlin-provided extension function that takes care of calling Lock.lock()/Lock.unlock() before/after invoking the supplied lambda.