前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >线程虚假唤醒

线程虚假唤醒

作者头像
九转成圣
发布2024-04-10 16:50:09
740
发布2024-04-10 16:50:09
举报
文章被收录于专栏:csdncsdn

线程虚假唤醒

标签:多线程

资源类

代码语言:javascript
复制
class MyResource {
    private int product;

    public synchronized void produce() {
        if (product > 10) {
            System.out.println(Thread.currentThread().getName() + " 即将等待 product 已满 " + product);
            try {
                wait();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println(Thread.currentThread().getName() + " 被唤醒 product 已满 " + product);
        }
        product++;
        System.out.println(Thread.currentThread().getName() + " 进货成功 " + product);
        // 每次都唤醒一下???
        notify();
    }

    public synchronized void consume() {

        if (product <= 0) {
        // while(product<=0){
            System.out.println(Thread.currentThread().getName() + " 即将等待 product 已空 " + product);
            
            try {
                wait();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println(Thread.currentThread().getName() + " 被唤醒product " + product);
        }
        product--;
        System.out.println(Thread.currentThread().getName() + "售货成功 " + product);
        // 每次都唤醒一下???
        notify();
    }
}

多线程使用资源类

代码语言:javascript
复制
public class FalseAwakeningExample {
    public static void main(String[] args) throws InterruptedException {
        MyResource resource = new MyResource();
        new Thread(() -> {
            for (int i = 0; i < 10; i++) {
                try {
                    Thread.sleep(100);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                resource.produce();
            }
        }, "生产者1").start();

        new Thread(() -> {
            for (int i = 0; i < 10; i++) {
                try {
                    Thread.sleep(100);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                resource.produce();

            }
        }, "生产者2").start();

        new Thread(() -> {
            for (int i = 0; i < 10; i++) {
                try {
                    Thread.sleep(100);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                resource.consume();
            }
        }, "消费者1").start();

        new Thread(() -> {
            for (int i = 0; i < 10; i++) {
                resource.consume();
            }
        }, "消费者2").start();
    }
}

说明:4个线程(2个消费者2个生产者)共同操作一个资源类,因为都要获取同一把锁,所以任何一时刻只有一个线程在运行.

虚假唤醒分析(if)

原因:生产者 消费者 锁的是同一个对象 生产者连续获得锁 生产者相互唤醒 过程:

  1. 消费者1获得锁 消费者1消费 因product=0消费者1等待
  2. 消费者2获得锁 消费者2消费 因product=0消费者2等待
  3. 生产者1获得锁,生成(product=1),唤醒消费者1
  4. 消费者1获得锁(product=1) 消费者1消费(product=0) 唤醒消费者2 消费者1再次消费因(product=0)消费者1wait
  5. 消费者2获得锁(product=0) 消费者2消费(product=-1) 唤醒消费者1 消费者2再次消费因(product=-1)消费者2wait
  6. 消费者1获得锁(product=-1) 消费者1消费(product=-2) 唤醒消费者2 消费者1再次消费因(product=-2)消费者1wait

解决虚假唤醒方案分析(while)

  1. 消费者1获得锁 消费者1消费 因product=0消费者1等待
  2. 消费者2获得锁 消费者2消费 因product=0消费者2等待
  3. 生产者1获得锁,生成(product=1),唤醒消费者1
  4. 消费者1获得锁(product=1) 消费者1消费(product=0) 唤醒消费者2 消费者1再次消费因(product=0)消费者1wait
  5. 消费者2获得锁(product=0) 因为还没有退出while循环,消费者2判断循环条件(product<=0),循环条件成立(product=0),消费者2再次wait
  6. 消费者1,消费者2均处于wait状态,等待生产者唤醒
本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2024-03-12,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 线程虚假唤醒
    • 标签:多线程
      • 资源类
        • 多线程使用资源类
        • 虚假唤醒分析(if)
        • 解决虚假唤醒方案分析(while)
        领券
        问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档