线程调用notifyAll唤醒其他线程之后

写在前面

今天做老师给的多线程的作业,熟悉线程之间通信的方法,像wait,notify,notifyAll,通过调试代码后,产生了很多疑问,我都纷纷作了猜测,唯有这个疑问我还没搞清楚,网上也难以翻到:线程调用notifyAll唤醒其他线程后其自身的状态是怎样的?我给的猜想是进入就绪队列中。

寻找答案

通过对下面代码的调试,理清楚线程的走向。

public class lab3_3 {
    public static void main(String[] args) {
        Object lock = new Object();
        MyThread3_3 t1 = new MyThread3_3(0, 'A', lock);
        MyThread3_3 t2 = new MyThread3_3(1, 'B', lock);
        MyThread3_3 t3 = new MyThread3_3(2, 'C', lock);
        t1.start();
        t2.start();
        t3.start();
    }
}

class MyThread3_3 extends Thread {
    Object lock;
    char c;
    int flag;
    static int current = 0; //意味着先输出A字符

    public MyThread3_3(int flag, char c, Object lock) {
        this.flag = flag;
        this.lock = lock;
        this.c = c;
    }

    @Override
    public void run() {
        for (int i = 0; i < 3; i++) {
*           synchronized (lock) {
                while (flag != current) {
                    try {
                        lock.wait();
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
                System.out.println(c);
                current = ++current % 3;
                lock.notifyAll();
            }
        }
    }
}

上面代码是控制顺序输出“ABCABCABC”。首先我在*处设下断点调试,按顺序先后让后两个线程②③获得锁,由于第一个字符A应该由线程①来获得锁并输出,所以此时线程②③会直接调用wait方法进入等待队列,如下图:

image-20200414221137081

然后线程①获得锁,执行代码块,输出字符,最后调用notifyAll方法唤醒其他线程,还没走完代码块,此时状态如下图,线程②③都为MONITOR,在这里我猜测该状态是线程就绪状态,没有确切的证据,因为我网上翻不到。

image-20200414221433114

接着走过代码块,来到for循环的判断语句时,状态开始变了,如下图:

image-20200414221728074

只有线程③进入RUNNING状态,线程②还是就绪状态,这里之前我又尝试了不同顺序的调用wait方法,比如一开始是线程②③的顺序调用wait方法,我又换了③②的顺序调用wait方法,发现上面的结果真的不一样,唤醒后变成了最后一个线程③在就绪队列中。明明是先调用wait方法先进入等待队列的,为什么不是最先从就绪队列出来的?网上有找到说就绪队列是队列形式但实际上采用线程池的形式,CPU调度不一定按先进先出的顺序调度。不过我又多给出三个线程来调试,发现都是最后调用wait的方法,就第一个从就绪队列进到RUNNING状态,不由得让我做出猜测:线程以堆栈的形式进入等待队列,然后出栈进入就绪队列,就绪队列是队列的数据结构,所以最后进入等待队列的线程,优先从就绪队列中出来。当然,确切的证据还是没有。

接着上面的步骤,直接让线程①获得锁执行代码块,发现线程它的状态变为MONITOR(就绪)了,没法再直接调用,此时也只能调用线程③了,由于当前是字符B的输出,也就是应该线程②获得锁,所以线程③又调用wait方法进入等待队列中,此时线程②从就绪队列中出来了,变为RUNNING状态。这个步骤我又尝试了多次其他不同的顺序,于是又给出猜测,也是适合这次内容主题的猜测:线程①调用notifyAll方法唤醒其他线程后,自身无法再直接获得该锁,进入了就绪队列,而且是队列的末尾,符合了队列的特征。

写在最后

我只是给出多个猜测,可能是正确的也说不定哈哈🤭我就暂且这样想吧,毕竟多线程还有好多内容呢,而且不记下来恐怕日后会烟消云散。能力之外的深入探究,就待我归来之时再谈吧。

天色已晚,就写到这里。

  • 0
    点赞
  • 0
    评论
  • 0
    收藏
  • 一键三连
    一键三连
  • 扫一扫,分享海报

相关推荐
<p style="color:#666666;"> <span style="font-size:14px;">本门课程重实战,将基础知识拆解到项目里,让你在项目情境里学知识。</span> </p> <p style="color:#666666;"> <span style="font-size:14px;">这样的学习方式能让你保持兴趣、充满动力,时刻知道学的东西能用在哪、能怎么用。</span> </p> <p style="color:#666666;"> <span style="font-size:14px;">平时不明白的知识点,放在项目里去理解就恍然大悟了。</span> </p> <p style="color:#666666;"> <span></span> </p> <p style="color:#666666;"> <span style="font-size:14px;"> </span> </p> <p style="color:#666666;"> <span style="color:#FF0000;font-size:14px;"><strong>一、融汇贯通</strong></span> </p> <p style="color:#666666;"> <span style="font-size:14px;">本视频采用了前后端分离的开发模式,前端使用Vue.js+Element UI实现了Web页面的呈现,后端使用Python 的Django框架实现了数据访问的接口,前端通过Axios访问后端接口获得数据。在学习完本章节后,真正理解前后端的各自承担的工作。</span> </p> <p style="color:#666666;"> <span style="font-size:14px;"> </span> </p> <p style="color:#666666;"> <span style="color:#FF0000;font-size:14px;"><strong>二、贴近实战</strong></span> </p> <p style="color:#666666;"> <span style="font-size:14px;">本系列课程为练手项目实战:学生管理系统v4.0的开发,项目包含了如下几个内容:项目的总体介绍、基本功能的演示、Vuejs的初始化、Element UI的使用、在Django中实现针对数据的增删改查的接口、在Vuejs中实现前端增删改查的调用、实现文件的上传、实现表格的分页、实现导出数据到Excel、实现通过Excel导入数据、实现针对表格的批量化操作等等,所有的功能都通过演示完成、贴近了实战</span> </p> <p style="color:#666666;"> <span style="font-size:14px;"> </span> </p> <p style="color:#666666;"> <span style="color:#FF0000;font-size:14px;"><strong>三、课程亮点</strong></span> </p> <p style="color:#666666;"> <span style="font-size:14px;">在本案例中,最大的亮点在于前后端做了分离,真正理解前后端的各自承担的工作。前端如何和后端交互</span> </p> <p style="color:#666666;"> <span style="font-size:14px;"> </span> </p> <p style="color:#666666;"> <span style="color:#FF0000;font-size:14px;"><strong>适合人群:</strong></span> </p> <p style="color:#666666;"> <span style="font-size:14px;">1、有Python语言基础、web前端基础,想要深入学习Python Web框架的朋友;</span> </p> <p style="color:#666666;"> <span style="font-size:14px;">2、有Django基础,但是想学习企业级项目实战的朋友;</span> </p> <p style="color:#666666;"> <span style="font-size:14px;">3、有MySQL数据库基础的朋友</span> </p> <p style="color:#666666;"> <span style="font-size:14px;"> </span> </p> <p style="color:#666666;"> <span style="font-size:14px;"><img alt="" src="https://img-bss.csdnimg.cn/202009070752197496.png" /><br /> </span> </p> <p style="color:#666666;"> <span style="font-size:14px;"><br /> </span> </p>
©️2020 CSDN 皮肤主题: 游动-白 设计师:白松林 返回首页
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值