生产者消费者模式中,等待条件判断 if 和 while 的区别

本文深入探讨了Java中线程同步的两种控制方式:if和while条件判断。通过具体的生产者-消费者模型实例,对比分析了两者在等待条件控制上的差异及影响,揭示了while循环在保证线程正确唤醒和资源状态一致性方面的重要性。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

说明:

有三个生产者,三个消费者(各三个线程代表)。当产品数为0时开始生产产品,生产一个后通知消费者消耗产品,之后又生产。所以一直在0和1中徘徊,正确输出为1和0交替出现。


一.if 控制等待条件,代码和结果如下

执行代码:Test

package com.hz.wjsc.mservice.syntheticwarfare.test.thread.produce;

public class Test {
    public static void main(String[] args) {
        Product p = new Product();
        for (int i = 0; i < 3; i++) {
            new Thread(() -> {
                try {
                    p.increment();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }, "生产者" + (i + 1)).start();
        }

        for (int i = 0; i < 3; i++) {
            new Thread(() -> {
                try {
                    p.decrement();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }, "消费者" + (i + 1)).start();
        }

    }
}

 产品代码:Product

package com.hz.wjsc.mservice.syntheticwarfare.test.thread.produce;

public class Product {

    private int number = 0;

    public synchronized void increment () throws InterruptedException {
        Thread.sleep(2000);
        if(number != 0) {
            System.out.println(Thread.currentThread().getName() +":要等待了,产品数:"+number);
            this.wait();
        }
        number++;
        System.out.println(Thread.currentThread().getName() + ":生产完成,产品数:" + number);
        this.notifyAll();
    }

    public synchronized void decrement () throws InterruptedException {
        if(number < 1) {
            Thread.sleep(200);
            System.out.println(Thread.currentThread().getName() +":要等待了,产品数:"+number);
            this.wait();
        }
        number--;
        System.out.println(Thread.currentThread().getName() + ":消费完成,产品数:" + number);
        this.notifyAll();
    }
}

 结果如下:

生产者1:生产完成,产品数:1
消费者3:消费完成,产品数:0
消费者2:要等待了,产品数:0
消费者1:要等待了,产品数:0
生产者2:生产完成,产品数:1
生产者3:要等待了,产品数:1
消费者1:消费完成,产品数:0
消费者2:消费完成,产品数:-1
生产者3:生产完成,产品数:0

结果:出现了-1,和预想不符合

分析:

  •  对于该类中的同步方法,一旦哪个线程进入执行别的线程就不能进入只能等待,除非别的方法执行完或者进入等待wait中,执行完和进入等待状态都会释放锁,而sleep不会释放锁
  • 进入等待的线程是不能参与线程间的竞争,唤醒后可以和别的线程公平竞争
  1. 生产者1抢占进入方法,完成生产,线程结束。产品数为1(生产者1进入方法后别的线程不能进入)
  2. 除生产者1外的5个线程公平竞争,消费者3一往无前抢占进入方法完成消费,线程结束。产品数为0
  3. 除生产者1、消费者3外的4个线程公平竞争,消费者2抢到了,但是产品数为0,进入if中等待。产品数为0
  4. 除生产者1、消费者3、消费者2外的3个线程公平竞争,消费者1抢到了,但是产品数为0,进入if中等待。产品数为0
  5. 除生产者1、消费者3、消费者2、消费者1外的2个线程公平竞争,生产者2抢到了完成生产,并唤醒了所有等待中的线程,线程结束。产品数为1
  6. 除生产者1、消费者3、生产者2外的3个线程公平竞争,生产者3抢到了,但是产品数为1,进入if中等待。产品数为1(消费者2、消费者1被叫醒了,又来抢了,抢的一身劲)
  7. 除生产者1、消费者3、生产者2、生产者3外的2个线程公平竞争,消费者1抢到了,完成消费,并唤醒了所有等待中的线程,线程结束。产品数为0
  8. 除生产者1、消费者3、生产者2、消费者1外的2个线程公平竞争,消费者2抢到了,此时虽然产品数为0,但消费者2是从if中醒来的,不会在判断进入if等待,直接向下执行,完成消费,并唤醒了所有等待中的线程,线程结束。产品数为-1
  9. 除生产者1、消费者3、生产者2、消费者1、消费者2外的1个线程公平竞争,生产者3不用抢了,完成生产,线程结束。产品数为0

出现问题:

   消费者2、消费者1先后进入等待,又先后唤醒执行,唤醒后不再进行if判断,也就和产品数无关了,直接消费出现问题

 

二.while控制等待条件

产品代码:Product

package com.hz.wjsc.mservice.syntheticwarfare.test.thread.produce;

public class Product {

    private int number = 0;

    public synchronized void increment () throws InterruptedException {
        Thread.sleep(2000);
        while(number != 0) {
            System.out.println(Thread.currentThread().getName() +":要等待了,产品数:"+number);
            this.wait();
        }
        number++;
        System.out.println(Thread.currentThread().getName() + ":生产完成,产品数:" + number);
        this.notifyAll();
    }

    public synchronized void decrement () throws InterruptedException {
        while(number < 1) {
            Thread.sleep(200);
            System.out.println(Thread.currentThread().getName() +":要等待了,产品数:"+number);
            this.wait();
        }
        number--;
        System.out.println(Thread.currentThread().getName() + ":消费完成,产品数:" + number);
        this.notifyAll();
    }
}

结果如下:

生产者1:生产完成,产品数:1
消费者2:消费完成,产品数:0
消费者3:要等待了,产品数:0
消费者1:要等待了,产品数:0
生产者3:生产完成,产品数:1
生产者2:要等待了,产品数:1
消费者1:消费完成,产品数:0
消费者3:要等待了,产品数:0
生产者2:生产完成,产品数:1
消费者3:消费完成,产品数:0

 分析:去除等待打印(3、4、6、8行)比上面(3、4、6行)多了一行,说明while比if多判断了一次并进入等待状态,就是1、0交替出现,没有问题

消费者3、消费者1先后进入if中等待,又先后被唤醒执行,消费者1执行完了后,产品数为0,此时消费者3又抢占开始执行方法,从wait处继续执行,但是while循环是无限循环,还是没有出循环体又判断了一波,产品数为0,又进入等待。关键是if只在进入方法的时候判断一次,而while不论进入方法还是唤醒后继续执行都会再判断一遍从而保证了正确性。

小伙伴们,不到之处还请斧正!


 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值