多线程下建议使用while而不用if进行循环

本文通过一个简单的Java生产者-消费者模型,展示了在多线程环境中如何使用while而非if判断信号量状态,确保线程安全。在队列满时阻塞set操作,队列空时阻塞get操作,利用wait和notifyAll方法协调线程,避免资源竞争错误。
摘要由CSDN通过智能技术生成

在多线程操作中,我们常常会遇到需要先判断信号量状态是否就绪,然后执行后续操作的场景。这里对状态的判断使用的是while而不是单线程下常用的if。

以下示例展示了一个简单的生产者-消费者模型:当队列满的时候,阻塞set;当队列为空的时候,阻塞get操作。

public class EventStorage {
    private int maxSize;
    private List<Date> storage;
    public EventStorage(){
        maxSize=10;
        storage=new LinkedList<>();
    }
    public synchronized void set(){
        while (storage.size()==maxSize){
            try {
                wait();
            } catch (InterruptedException e) {
            e.printStackTrace();
            }
        }
        storage.offer(new Date());
        System.out.printf("Set: %d",storage.size());
        notifyAll();
    }
    public synchronized void get(){
        while (storage.size()==0){
            try {
                wait();
            } catch (InterruptedException e) {
            e.printStackTrace();
            }
        }
        System.out.printf("Get: %d: %s",storage.
        size(),((LinkedList<?>)storage).poll());
        notifyAll();
    }
}
public class Producer implements Runnable {
    private EventStorage storage;
    public Producer(EventStorage storage){
        this.storage=storage;
    }
    @Override
    public void run() {
        for (int i=0; i<100; i++){
            storage.set();
        }
    }
 }
public class Consumer implements Runnable {
    private EventStorage storage;
    public Consumer(EventStorage storage){
        this.storage=storage;
    }
    @Override
    public void run() {
        for (int i=0; i<100; i++){
            storage.get();
        }
    }
}
public class Main {
    public static void main(String[] args) {
        EventStorage storage=new EventStorage();
        Producer producer=new Producer(storage);
        Thread thread1=new Thread(producer);
           Consumer consumer=new Consumer(storage);
         Thread thread2=new Thread(consumer);
           thread1.start();
        thread2.start();
    }
}

原因:
在线程中notify或者notifyAll会唤醒一个或多个线程,当线程被唤醒后,被唤醒的线程继续执行阻塞后的操作。

这里分析一下get操纵: 当某个线程得到锁时storage为空,此时它应该wait,下次被唤醒时(任意线程调用notify),storage可能还是空的。因为有可能其他线程清空了storage。如果此时用的是if它将不再判断storage是否为空,直接继续,这样就引起了错误。但如果用while则每次被唤醒时都会先检查storage是否为空再继续,这样才是正确的操作;生产也是同一个道理。

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值