Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Correctly implementing wait and notify in Kotlin

Tags:

kotlin

According to this document, using wait and notify is discouraged in Kotlin: https://kotlinlang.org/docs/reference/java-interop.html

wait()/notify()

Effective Java Item 69 kindly suggests to prefer concurrency utilities to wait() and notify(). Thus, these methods are not available on references of type Any.

However the document does not propose any correct way of doing it.

Basically, I would like to implement a service, which would read the input data and process them. If there were no input data, it would suspend itself until someone notifies that there are new input data. Something like

while (true) {     val data = fetchData()     processData(data)     if (data.isEmpty()) {         wait()     } } 

EDIT:

I don't want to use these not recommended methods (antipatterns), I really want to find out how to do this properly.

In my case fetchData reads data from the database, so queues in my case cannot be used.

like image 391
Vojtěch Avatar asked Jun 16 '17 12:06

Vojtěch


People also ask

How do you use wait and notify?

The wait() Method Simply put, calling wait() forces the current thread to wait until some other thread invokes notify() or notifyAll() on the same object. For this, the current thread must own the object's monitor.

How do wait () notify () and notifyAll () work?

The wait() method causes the current thread to wait until another thread invokes the notify() or notifyAll() methods for that object. The notify() method wakes up a single thread that is waiting on that object's monitor. The notifyAll() method wakes up all threads that are waiting on that object's monitor.

Why wait () notify () and notifyAll () methods have to be called from synchronized method or block?

wait method tells the current thread (thread which is executing code inside a synchronized method or block) to give up monitor and go to waiting state. notify method wakes up a single thread that is waiting on this object's monitor. notifyAll method wakes up all the threads that called wait() on the same object.


1 Answers

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.

like image 150
Laurence Gonsalves Avatar answered Oct 27 '22 01:10

Laurence Gonsalves