生产者与消费者问题JUC

生产者与消费者问题

Synchronized版

package com.cz.demo1;

/**
 * @author 卓亦苇
 * @version 1.0
 * 2023/3/2 9:55
 */
public class TestConsumer {
    public static void main(String[] args) {
        Data data = new Data();
        new Thread(()->{
            for (int i = 0; i < 10; i++) {
                data.increment();
            }
        },"A").start();
        new Thread(()->{
            for (int i = 0; i < 10; i++) {
                data.decrement();
            }
        },"B").start();
    }
}

class Data{
    private int num = 0;


    public synchronized void increment(){
        if (num!=0){
        try {
            this.wait();
        } catch (InterruptedException e) {
            throw new RuntimeException(e);
        }
        }
        System.out.println(Thread.currentThread().getName()+"生产了"+num);
        num++;
        this.notifyAll();
    }

    public synchronized void decrement(){
        if (num==0) {
            try {
                this.wait();
            } catch (InterruptedException e) {
                throw new RuntimeException(e);
            }
        }
        System.out.println(Thread.currentThread().getName() + "消费了" + num);
        num--;
        this.notifyAll();
    }

}

问题存在,多个线程状态下是否安全?

image-20230302101531817

存在虚假唤醒

if改为while

package com.cz.demo1;

/**
 * @author 卓亦苇
 * @version 1.0
 * 2023/3/2 9:55
 */
public class TestConsumer {
    public static void main(String[] args) {
        Data data = new Data();
        new Thread(()->{
            for (int i = 0; i < 10; i++) {
                data.increment();
            }
        },"A").start();

        new Thread(()->{
            for (int i = 0; i < 10; i++) {
                data.increment();
            }
        },"C").start();

        new Thread(()->{
            for (int i = 0; i < 10; i++) {
                data.decrement();
            }
        },"B").start();
    }
}

class Data{
    private int num = 0;


    public synchronized void increment(){
        while (num!=0){
        try {
            this.wait();
        } catch (InterruptedException e) {
            throw new RuntimeException(e);
        }
        }
        System.out.println(Thread.currentThread().getName()+"生产了"+num);
        num++;
        this.notifyAll();
    }

    public synchronized void decrement(){
        while (num==0) {
            try {
                this.wait();
            } catch (InterruptedException e) {
                throw new RuntimeException(e);
            }
        }
        System.out.println(Thread.currentThread().getName() + "消费了" + num);
        num--;
        this.notifyAll();
    }

}

JUC版的生产者与消费者问题

package com.cz.demo1;

/**
 * @author 卓亦苇
 * @version 1.0
 * 2023/3/3 9:14
 */

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

/**
 * JUC版本生产者与消费者问题,利用Lock锁来实现
 */
public class TestConsumer2 {
    public static void main(String[] args) {
        Date2 date2 = new Date2();

        new Thread(()->{
            for (int i = 0; i < 10; i++) {
                date2.increment();
            }
        },"A").start();
        new Thread(()->{
            for (int i = 0; i < 10; i++) {
                date2.decrement();
            }
        },"B").start();
        new Thread(()->{
            for (int i = 0; i < 10; i++) {
                date2.increment();
            }
        },"C").start();
        new Thread(()->{
            for (int i = 0; i < 10; i++) {
                date2.decrement();
            }
        },"D").start();
    }

}

class Date2{
    private int num = 0;
    Lock lock = new ReentrantLock();
    Condition condition = lock.newCondition();



    public void increment(){
        lock.lock();
        try {
            while (num!=0) {
                condition.await();
            }
            num++;
            System.out.println(Thread.currentThread().getName() + "生产了" + num);
            condition.signalAll();
        } catch (InterruptedException e) {
            throw new RuntimeException(e);
        } finally {
            lock.unlock();
        }
    }


    public void decrement(){
        lock.lock();
        try {
            while (num==0) {
                condition.await();
            }
            num--;
            System.out.println(Thread.currentThread().getName() + "消费了" + num);
            condition.signalAll();
        } catch (InterruptedException e) {
            throw new RuntimeException(e);
        } finally {
           lock.unlock();
        }
    }
}

condition优势

可以精准通知和唤醒线程

image-20230303094530429

原来的线程执行时由CPU自行调度,利用condition可以精准通知和唤醒线程

posted @   卓亦苇  阅读(21)  评论(0编辑  收藏  举报
编辑推荐:
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 基于Microsoft.Extensions.AI核心库实现RAG应用
· Linux系列:如何用heaptrack跟踪.NET程序的非托管内存泄露
阅读排行:
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· 阿里巴巴 QwQ-32B真的超越了 DeepSeek R-1吗?
· 【译】Visual Studio 中新的强大生产力特性
· 【设计模式】告别冗长if-else语句:使用策略模式优化代码结构
· AI与.NET技术实操系列(六):基于图像分类模型对图像进行分类
点击右上角即可分享
微信分享提示