并发编程中的三个问题

现在我们来学习第一章的内容,并发编程中存在的三个问题。

我们在使用多线程进行并发编程的时候,如果同时有多个线程来操作共享数据,那么很有可能这个共享数据它的值会出现错乱,那么我们称之为线程安全问题。那么导致这个线程安全问题的根本原因有这三个,第一个是可见性问题,第二个是原子性问题,第三个是有序性问题。那么我们这一章节就重点来学习这三个问题。

可见性问题

目标:那么咱们先看第一个目标,学习什么是可见性问题。咱们讲解的步骤分成两个。第一个介绍可见性的概念,第二个通过一个案例来演示可见性问题。

那么我们在讲解可见性概念之前,要注意他的几个前提条件。第一个如果只有一个线程来操作,那么就肯定不会存在这个线程间的可见性问题。第二个还需要有共享数据,如果没有共享数据,那么也不存在可见性的问题。

可见性是指一个线程对共享变量进行修改,另一个线程要立即得到修改后的最新值。

接下来我们就通过代码来演示可见性问题。

案例:

目标:演示可见性问题。

步骤:

​ 1、创建一个共享变量。
​ 2、要创建多条线程,其中一条线程来不断读取共享变量,另外再创建一条线程,然后修改共享,我们看前一条线程能不能立马得到修改后的最新值。

public class VisibilityTestDemo01 {
    // 1、创建一个共享变量
    private static boolean flag = true;


    public static void main(String[] args) throws InterruptedException {
        // 2、创建一条线程不断读取共享变量
        new Thread(() -> {
            while (flag) {

            }
        }).start();
        //让线程休眠 2 秒
        Thread.sleep(2000);

        //3、创建一条线程修改共享变量
        new Thread(() -> {
            flag =false;
            System.out.println("修改共享变量的线程修改了变量的值为 false。");
        }).start();


    }
}

我们先来分析一下这段代码,我们程序 main 方法执行,然后开启了一个读取共享变量线程,一个修改共享变量线程,我们多线程执行具有随机性,有可能先跑读取共享变量线程的。有可能先跑修改共享变量线程,如果先跑修改共享变量线程的,咱们就看不到循环了。为了让这个效果更加明显一点,这里加一个 sleep 方法,让线程休眠 2 秒,这样的话就更加明显的来分析问题。

按照我们现在所学的知识点。那么首先执行 main 方法的时候,会创建出一个读取共享变量线程,那么这个线程会来读取共享变量值。所读取到的是 flag 的值是 true,所以 while 循环会一直进行,当主线程数了两秒之后,又会启动一个修改共享变量线程,将 flag 的值变成了 false。那么问题是读取共享变量线程中的 flag 的值有没有变成 false 呢?如果有,那么他就会停下来。如果没有,他就还会继续。

程序运行的结果:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-LMASDSNl-1626314440431)(img/image-20210118004925896.png)]

在两秒看这边已经输出了线程将 flag 值修改 false。但是咱们的程序并没有结束,也就意味着读取共享变量线程还在 while 循环中执行着,认为 while 中的的变量还是 true,所以还在循环并没有停止。那么这个时候同学们就看到了,是不是咱们并发编程就出现了可见性问题,修改共享变量线程对变量的修改,我们读取共享变量线程并没有立即得到最新的结果。

小结:当我们并发编程的时候,如果有多线程来操作共享变量,一个线程来读,一个线程来写,那么可能会出现线程安全问题,就是一个线程进行变量的修改,另外一个线程并没有立马得到修改后的最新值。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值