前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >Java 线程的虚假唤醒

Java 线程的虚假唤醒

作者头像
JavaEdge
发布2021-02-22 14:26:12
3090
发布2021-02-22 14:26:12
举报
文章被收录于专栏:JavaEdge

最近在学习Java多线程设计的时候,在网上看到一个面试题目的讨论,虽然楼主所说有些道理,但感觉还是有些问题,故此在和同事讨论以后还是有了若干收获,在此略作总结。

首先,来看看这个面试题目吧。

代码语言:javascript
复制
public class MyStack { 
    private List list = new ArrayList(); 
 
    public synchronized void push(String value) { 
        synchronized (this) { 
            list.add(value); 
            notify(); 
        } 
    } 
 
    public synchronized String pop() throws InterruptedException { 
        synchronized (this) { 
            if (list.size() <= 0) { 
                wait(); 
            } 
            return list.remove(list.size() - 1); 
        } 
    } 
} 

问题: 这段代码大多数情况下运行正常,但是某些情况下会出问题。什么时候会出现什么问题?如何修正?

代码分析:

从整体上,在并发状态下,push和pop都使用了synchronized的锁,来实现同步,同步的数据对象是基于List的数据;大部分情况下是可以正常工作的。

问题描述:

状况1:

  1. 假设有三个线程: A,B,C. A 负责放入数据到list,就是调用push操作, B,C分别执行Pop操作,移除数据。
  2. 首先B先执行,于pop中的wait()方法处,进入waiting状态,进入等待队列,释放锁。
  3. A首先执行放入数据push操作到List,在调用notify()之前; 同时C执行pop(),由于synchronized,被阻塞,进入Blocked状态,放入基于锁的等待队列。注意,这里的队列和2中的waiting等待队列是两个不同的队列。
  4. A线程调用notify(),唤醒等待中的线程A。
  5. 如果此时, C获取到基于对象的锁,则优先执行,执行pop方法,获取数据,从list移除一个元素。
  6. 然后,A获取到竞争锁,A中调用list.remove(list.size() - 1),则会报数据越界exception。

状况2:

  1. 相同于状况1
  2. B、C都处于等待waiting状态,释放锁。等待notify()、notifyAll()操作的唤醒。
  3. 存在被虚假唤醒的可能。

何为虚假唤醒?

虚假唤醒就是一些obj.wait()会在除了obj.notify()和obj.notifyAll()的其他情况被唤醒,而此时是不应该唤醒的。

解决的办法是基于while来反复判断进入正常操作的临界条件是否满足:

代码语言:javascript
复制
synchronized (obj) { 
        while () 
            obj.wait(); 
        ... // Perform action appropriate to condition 
    } 

如何修复问题?

#1. 使用可同步的数据结构来存放数据,比如LinkedBlockingQueue之类。由这些同步的数据结构来完成繁琐的同步操作。

#2. 双层的synchronized使用没有意义,保留外层即可。

#3. 将if替换为while,解决虚假唤醒的问题。

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2020/04/21 ,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
相关产品与服务
腾讯云代码分析
腾讯云代码分析(内部代号CodeDog)是集众多代码分析工具的云原生、分布式、高性能的代码综合分析跟踪管理平台,其主要功能是持续跟踪分析代码,观测项目代码质量,支撑团队传承代码文化。
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档