java线程的一个细节解读-记一个网络教程的错误

我的职业生涯中主要的编码语言是C++。最近这10年虽然做的大多数项目都是java项目,但是自己写的java代码十分有限,也没有系统地学习过java语言。最近整好有时间,系统地学习一遍java的基础知识。选用了尚硅谷的一套视频教程作为学习材料。

今天在学习线程部分的时候,发现其中一节讲解的线程知识,和我对操作系统的线程知识的理解是相矛盾的,不确定是我记忆出错了,还是现在的系统已经改变成不是我原来理解的样子了,于是编码验证,确定确实视频教程的内容是不正确的,当前操作系统运行线程的基本原理和我的理解的并无差异。于是有了这篇文章,希望有相同理解偏差的朋友、同行们能得以纠正,避免因此引发不可知的错误(此错误在大多数情况下,并不会导致错误的业务结果)。

原始视频内容在这里:【【尚硅谷】7天搞定Java基础,Java零基础极速入门】https://www.bilibili.com/video/BV1o841187iP?p=129&vd_source=985bb3ae9715d207fa85a720b898c08b

这个章节讲的是线程的串行执行和并发。

对应的源代码如下:

package chapter09;

public class java02_thread {
    public static void main(String[] args) throws InterruptedException {

        MyThread1 t1 = new MyThread1();
        MyThread2 t2 = new MyThread2();

        t1.start();
        t2.start();

        //  将线程连接成串
        t1.join();
        t2.join();

        System.out.println("main");
    }
}

class MyThread1 extends Thread {
    @Override
    public void run() {
        System.out.println("mythread1");
    }
}
class MyThread2 extends Thread {
    @Override
    public void run() {
        System.out.println("mythread2");
    }
}

视频中说

// 将线程连接成串

t1.join();

t2.join();

这一段代码的两个join,能保障t1线程先执行完,然后再执行t2线程,这就叫做串行执行。依据我对操作系统线程运行原理和pthread模型中对线程join方法的抽象的理解,结果不应该是这个样子的。

于是,写代码验证,运行了很多次,结果一直是:

不信邪,继续运行,直到运行了10多次后,终于出现了不一样的结果了:

出现这个结果,已经充分说明这段代码中的join其实是无法保证两个线程的串行执行的。

其实为了更快验证结果,把以上两行代码调换一下顺序:

t2.join();

t1.join();

你会发现,大多数时候并不是thread2先结束,还是thread1先结束。这也证明了,线程执行的顺序和join的顺序其实是无关的。

(感兴趣的同学可以使用我上面的代码自行验证)。

那么为什么会是这样的结果呢?这个要从join这个操作的行为说起了。join这个操作并不是控制线程执行的,它其实是在这一行代码这里等待这个线程执行完毕,然后才会去运行下一行代码。也就是说,样例中的代码,只是确保先等t1运行结束,然后再运行t2.join(),t2.join()的行为是什么呢?它先看看t2到底结束了没有,如果没有就在这里等待,等到t2结束,再去运行下一行。其实它本身既不能控制目标线程什么时候开始执行,也不能控制目标线程什么时候结束,而是让当前线程等待目标线程结束再继续,实际的结果是把当前的线程挂起,去等待目标线程结束。

如果程序员把这个教程的说法当作正确的知识吸收,将来在用这个特性编写真的需要业务功能的时候,是有一定的几率遇到和预期不一致的结果的。而这种结果很难调试,很难识别。所以大家需要对类似的错误加以重视。也希望在网上发布教程的同行们,要加强专业性,并能及时纠错。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值