Languages
[Edit]
EN

Java concurrency - avoid busy wait using wait() and notify() inter-thread communication methods

7 points
Created by:
maxsior322
347

In this article, we would like to show to to avoid busy wait using wait() and notify() inter-thread communication methods in Java.

Note: the preseted approach is not the best choice to synchronize threads, but in this post we use it for learning purpose.

Quick solution:

// shared objects:

int counter = 0;            // e.g. as class field
Object lock = new Object(); // e.g. as class field

// thread 1:

Thread thread1 = new Thread(() -> {
    // ...
    // do task 1
    // ...
    synchronized(lock) {
        counter++;
        lock.notify();
    }
});

// thread 2:

Thread thread2 = new Thread(() -> {
    // ...
    // do task 2
    // ...
    synchronized(lock) {
        counter++;
        lock.notify();
    }
});

// e.g. in main thread - runs tasks and waits until are ended:

synchronized(lock) {
    thread1.start();
    thread2.start();
    while(counter < 2) {
        lock.wait();
    }
}

 

Practical example

The main idea of the presented solution is to use synchronized keyword to control and exchange tasks state between threads. It prevents against same-time critical sections execution by different threads. counter object helps to detect when all tasks are done. The main thread waits for notification from other threads when some task is done - when notify() is called, wait() method is unblocekd once.

Warning:

It is not good idea to use wait() and notify() methods, because there is always risk the notify() will be executed before wait() leaving program blocked.

Source code: 

public class Program {

    public static void main(String[] args) throws InterruptedException {

        // shared objects:

        final Object lock = new Object();
        final Counter counter = new Counter(); // we use Couter class to control state from lambdas

        // [Thread: Thread-0] - Task 1

        Thread thread1 = new Thread(() -> {
            printMessage("task 1 started");
            try {
                simulateTask(300); // longer task
            } finally {
                printMessage("task 1 done");
                synchronized (lock) {
                    counter.increment();
                    lock.notify();
                }
            }
        });

        // [Thread: Thread-1] - Task 2

        Thread thread2 = new Thread(() -> {
            printMessage("task 2 started");
            try {
                simulateTask(100); // shorter task
            } finally {
                printMessage("task 2 done");
                synchronized (lock) {
                    counter.increment();
                    lock.notify();
                }
            }
        });

        // [Thread: main]

        synchronized (lock) {
            counter.reset();
            thread1.start();
            thread2.start();
            printMessage("tasks started");
            while (counter.get() < 2) {
                lock.wait();
                printMessage("thread notified");
            }
            printMessage("tasks done");
        }
    }

    // helper methods

    private static void simulateTask(int timeout) {
        try {
            Thread.sleep(timeout);
        } catch (InterruptedException e) {
             e.printStackTrace();
        }
    }

    private static void printMessage(String message) {
        Thread thread = Thread.currentThread();
        System.out.println("[" + thread.getName() + "]: " + message);
    }

    // helper classes

    private static class Counter {

        private int value = 0;

        private int get() {
            return this.value;
        }

        private void increment() {
            this.value += 1;
        }

        private void reset() {
            this.value = 0;
        }
    }
}

Output:

[main]: tasks started
[Thread-1]: task 2 started
[Thread-0]: task 1 started
[Thread-1]: task 2 done
[main]: thread notified
[Thread-0]: task 1 done
[main]: thread notified
[main]: tasks done

 

See also

  1. What is busy waiting lock?

Donate to Dirask
Our content is created by volunteers - like Wikipedia. If you think, the things we do are good, donate us. Thanks!
Join to our subscribers to be up to date with content, news and offers.

Java concurrency

Native Advertising
🚀
Get your tech brand or product in front of software developers.
For more information Contact us
Dirask - we help you to
solve coding problems.
Ask question.

❤️💻 🙂

Join