zoukankan      html  css  js  c++  java
  • 多线程操作中为什么使用while而不是if来做判断状态是否就绪

    在多线程操作中,我们常常会遇到需要先判断信号量状态是否就绪,然后执行后续操作的场景。这里对状态的判断使用的是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();
        }
    }

    在set中使用了

    while (storage.size()==maxSize){
             try {
                wait();
           } catch (InterruptedException e) {
            e.printStackTrace();
           }
       }

    在get中使用了

    while (storage.size()==0){
           try {
               wait();
           } catch (InterruptedException e) {
               e.printStackTrace();
         }
    }

    原因:

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

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

  • 相关阅读:
    PHP四种基础算法详解
    Webuploader教程(一)------简单实用上传功能
    macOS Sierra上面的php开发环境安装
    mac lamp环境 apache文件配置
    mysql 通过拷贝data文件夹进行恢复。
    mysql 执行 cannot found mac安装mysql的两种方法(含配置)
    mac 终端里进入mysql和退出
    macOS Sierra安装Apache2.4+PHP7.0+MySQL5.7.16
    Javascript基础知识
    2016年6月份基础学习要求
  • 原文地址:https://www.cnblogs.com/limingluzhu/p/4325784.html
Copyright © 2011-2022 走看看