Skip to content
JackSparrow414
Go back

Locks in Java (Part 3): Implementing Wait and Notify with Condition

Table of contents

Open Table of contents

Locks in Java (Part 3)

Using Condition

Using Condition with Lock is equivalent to using wait/notify with synchronized.

Methods in Condition

  1. void await() = wait
  2. void await(long nanos) with a timeout = wait(long timeout)
  3. void signal = notify wake one waiting thread
  4. void signalAll() = notifyAll wake all waiting threads

Important Points

As with wait and notify, you must acquire the lock before calling await, signal, or signalAll.

Implementing Wait and Notify

import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
import lombok.SneakyThrows;
import org.junit.Test;

/**
 * Combine Lock and Condition to implement waiting and notification. Remember to release the lock. All waiting and notification operations must take place between lock and unlock.
 *
 * Lock lock = new ReentrantLock();
 * Condition condition = lock.newCondition();
 * lock.lock;/lock.tryLock();/lock.tryLock(long nanos)
 * try{
 *     condition.await();/condition.await(long nanos);/condition.signal();/condition.signalAll();
 * } finally {
 *     lock.unlock();
 * }
 *
 * @author jacksparrow414
 * @date 2020/10/21
 */
public final class ThreadLockConditionTest {

    // Reentrant lock; nonfair by default
    static Lock lock = new ReentrantLock();
    static Condition condition = lock.newCondition();
    static boolean flag = true;

    @Test
    @SneakyThrows
    public void assertLockCondition() {
        Thread threadN = new Thread(new ThreadLockConditionTest.threadN(), "threadN");
        Thread threadM = new Thread(new ThreadLockConditionTest.threadM(), "threadM");
        threadN.start();
        TimeUnit.SECONDS.sleep(1);
        threadM.start();
        TimeUnit.SECONDS.sleep(10);
    }

    static class threadN implements Runnable {

        @Override
        public void run() {
            // Do not put lock acquisition inside the try block. If an exception occurs while acquiring a custom lock,
            //the exception could also cause the lock to be released incorrectly.
            lock.lock();
            while (flag) {
                System.out.println(Thread.currentThread().getName() + " flag is true wait");
                try {
                    condition.await();
                } catch (InterruptedException exception) {
                    exception.printStackTrace();
                } finally {
                    // Remember to release the reentrant lock manually
                    lock.unlock();
            }
            System.out.println(Thread.currentThread().getName() + "falg is false running");
            }
        }
    }

    static class threadM implements  Runnable {

        @Override
        public void run() {
            lock.lock();
            System.out.println(Thread.currentThread().getName() + " acquire lock");
            flag = false;
            // Wake all waiting threads
            try {
                TimeUnit.SECONDS.sleep(3);
                condition.signalAll();
            } catch (InterruptedException exception) {
                exception.printStackTrace();
            }finally {
                lock.unlock();
            }
            // The operation that wakes waiting threads must be inside the synchronized section, or an error will occur
            // condition.signalAll();
            lock.lock();
            System.out.println(Thread.currentThread().getName() + " acquire again");
            condition.signalAll();
            lock.unlock();
        }

    }
}

Share this post:

Continue this series

Locks in Java

  1. Locks in Java (Part 1): Lock Categories
  2. Locks in Java (Part 2): Implementing a Custom Lock
  3. Locks in Java (Part 3): Implementing Wait and Notify with ConditionYou are here
  4. Locks in Java (Part 4): High-Performance Web Page Caching with a Read-Write Lock

Comments

Questions, corrections, and experiences are welcome. Sign in with GitHub to comment; both language versions share this discussion.

Comments are available on the live site only.