zoukankan      html  css  js  c++  java
  • 为什么wait和notify只能在synchronized中?

    前言

    wait和notify必须在synchronized块中,否则会抛出IllegalMonitorStateException。

    原因

    代码示例

    class BlockingQueue {
        Queue<String> buffer = new LinkedList<String>();
    
        public void give(String data) {
            buffer.add(data);
            notify();                   
        }
    
        public String take() throws InterruptedException {
            while (buffer.isEmpty())    
                wait();
            return buffer.remove();
        }
    }
    

    代码示例的问题所在

    一个消费者调用take,发现buffer.isEmpty。
    在消费者调用wait之前,由于cpu的调度,消费者线程被挂起,生产者调用give,然后notify。
    然后消费者调用wait (注意,由于错误的条件判断,导致wait调用在notify之后,这是关键)。
    如果很不幸的话,生产者产生了一条消息后就不再生产消息了,那么消费者就会一直挂起,无法消费,造成死锁。

    关键

    总是让give/notify和take/wait为原子操作。wait/notify是线程之间的通信,他们存在竞态,我们必须保证在满足条件的情况下才进行wait。换句话说,如果不加锁的话,那么wait被调用的时候可能wait的条件已经不满足了(如上述)。由于错误的条件下进行了wait,那么就有可能永远不会被notify到,所以我们需要强制wait/notify在synchronized中。

  • 相关阅读:
    shell 脚本语法
    discuz pre_forum_postposition表说明
    PHP调试工具Xdebug安装配置教程
    检查用户头像状态的脚本
    PHP 性能监测
    Mysql 索引优化
    MySQL主从复制配置
    vue mixin 混入
    vue渲染方式:render和template的区别
    vue自定义指令directive Vue.directive() directives
  • 原文地址:https://www.cnblogs.com/jichi/p/12694173.html
Copyright © 2011-2022 走看看