This is the 23rd day of my participation in the August More Text Challenge.More challenges in August

Producer-consumer problem

Producer consumer problem is a classic problem of thread communication. Two role producer consumers, they share the same resource space, the consumer blocks when the space is empty, and the producer blocks when the space is full.

example

A variable with an initial value of 0 is operated on by two threads, alternately adding one and subtracting one

package com.lemon;

import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

public class lesson8_Consumer {
    public static void main(String[] args) {
        ResourceInfo resourceInfo = new ResourceInfo();
        new Thread(() -> {
            for (int i = 0; i < 5; i++) {
                try {
                    resourceInfo.increment();
                } catch(InterruptedException e) { e.printStackTrace(); }}},"AAA").start();
        new Thread(() -> {
            for (int i = 0; i < 5; i++) {
                try {
                    resourceInfo.decrement();
                } catch(InterruptedException e) { e.printStackTrace(); }}},"BBB").start(); }}class ResourceInfo {
    private ReentrantLock lock = new ReentrantLock();
    private Condition condition = lock.newCondition();
    private int num;

    public void increment(a) throws InterruptedException {
        lock.lock();
        try {
            while(num ! =0) {
                condition.await(); // Waiting cannot produce
            }
            num++;
            System.out.println(Thread.currentThread().getName() + "\t num:" + num);
            condition.signalAll(); // Wake up notification
        } catch (Exception e) {
            e.printStackTrace();
        } finally{ lock.unlock(); }}public void decrement(a) throws InterruptedException {
        lock.lock();
        try {
            while (num == 0) {
                condition.await();
            }
            num--;
            System.out.println(Thread.currentThread().getName() + "\t num:" + num);
            condition.signalAll();
        } catch (Exception e) {
            e.printStackTrace();
        } finally{ lock.unlock(); }}}Copy the code

Why use while instead of if to determine the value of num?

False awaken

When a condition is met, many threads are woken up, but some are uselessly woken up. If num was 0 and num was 1 after production, it would wake up other consumers to consume, but in fact num=1 would only be consumed by one consumer.

There is no false wake up in the while: the thread is woken up and rejudges the condition in the while before executing the code that follows it through the while loop

If has a false wake up: the thread will run from the code after wait, but will continue to run the code after the if block without rejudging the if condition

Object -> wait -> in jdk1.8:

Threads can also wake up without being notified, interrupted or timed out, a so-called false wake up. Although this rarely happens in practice, the application must guard against it by testing the condition that should cause the thread to wake up, and continue to wait if the condition is not met. In other words, waiting should always occur in the loop, like this:

            synchronized (obj) {
                     while(<condition does not hold>) obj.wait(timeout); .// Perform action appropriate to condition
                 } 
Copy the code