【无标题】

wait和notify为什么必须写在synchronized代码块中

    • 1.1简介
    • 1.2论证

1.1简介

waitnotify 常见应用在线程通信中,例如经典的生产者消费者问题。

wait阻塞当前线程。 notify唤醒阻塞的线程(一个)。 notifyAll唤醒阻塞的线程(全部)。

waitnotify要成对出现,如果不写在synchronized中,在并发执行的情况下会出现程序执行混乱的情况。waitnotify保证的是线程的相对执行顺序,sychronized保证的是原子性,可见性,有序性。两者相互配合使用可利用全局变量实现线程通信。

1.2论证

拿经典的生产者消费者为例:

package study;

public class Message {
    //初始产品数量
    private int capSize = 0;
    //最大产品数量
    private int maxSize = 20;

    //生产消息
    public synchronized void produceMsg() throws InterruptedException {
        if(capSize < maxSize){
            //消息未满,生产消息,唤醒消费者
            capSize++;
            System.out.println("produce remain num:"+capSize);
            notifyAll();
        }else{
            //消息已满,阻塞生产者
            System.out.println("produce alread is max");
            wait();
        }
    }

       //消费消息
    public synchronized void consumeMsg() throws InterruptedException {
        //无可消费消息,阻塞消费者
        if(capSize <=0){
            notifyAll();
        }else{
            //有可消费消息,消费消息
        	capSize--;
       		System.out.println("consume remain num:"+capSize);
        } 
    }
}

假设,waitnotify不必写在sychronized代码块中

如果去除sychronized关键字,当前商品数量为19时,两个生产者线程同时生产商品,即执行capSize++,因为没有并发控制,结果可能为20,出现了数据丢失的情况。以此可以证明 waitnotify必须在synchronized代码块中出现

你可能感兴趣的:(多线程和并发,多线程,线程通信,java)