b2科目四模拟试题多少题驾考考爆了怎么补救
b2科目四模拟试题多少题 驾考考爆了怎么补救

【案例分析】主线程之间数据共享案例(一)

电脑杂谈  发布时间:2021-01-23 13:10:43  来源:网络整理

Java并发易失关键字内存可见性问题

线程之间的数据共享情况

让我们先来看一个场景:

启动Main函数后,调用一个线程将数据添加到列表中。当列表的大小为5时,将变量标志设置为true。然后,主线程根据该标志的值执行其他操作。

代码如下:

编辑

运行结果:

编辑

我们发现,当子线程将标志输出为true时,主线程不会输出=====。

这是为什么?

volatile 内存屏障_volatile 内存可见性_volatile内存模型

在内存中运行的线程的简化图

让我们看看上面的程序如何在内存中运行

编辑

操作说明:

程序运行时,从主函数主线程开始,主线程首先将flag = false复制到其自身程序的内存中;

这时,子线程被启动,并且子线程还将flag = false复制到其自己的程序存储器中。执行完自己的内部代码后,它会修改flag的值,并将其写回到主内存(相对于程序自己的内存)。换句话说,存储器中的数据是主存储器。该程序自己的内存实际上是主内存中数据的副本。

如下所示:

编辑

volatile 内存可见性_volatile内存模型_volatile 内存屏障

由于未刷新主线程,因此无法从主线程获得最新的标志值。因此,===永远不会在控制台上输出。

结果分析

那为什么会发生呢? [这里您需要了解两个概念:编译器和注册]

那是因为编译器会自动优化结果。

编译器优化:程中,当读取一个变量时,为了提高读写(访问)的速度,编译器将首先将该变量读入一个寄存器(对应于Picture子线程自己的内存)或主线程自己的内存);将来在获取此变量时,将直接从寄存器中获取它。

在此线程中更改变量的值时,变量的新值将同时同步到寄存器以保持一致性;同时,JVM将向处理器发送一条指令,以更改该变量所在的寄存器的值。该值将写回到系统内存(与上图中的主内存相对应)。

数据不一致的原因:

当变量由于其他线程操作而改变其值时,寄存器的值将不会相应地改变,从而导致应用程序读取的值与实际变量值不一致(如上述模式示例中,子线程更改标志的值,但不会修改主线程寄存器中的值(从变量的角度来看);

或者当寄存器由于其他线程而更改变量的值时,变量的原始值将不会更改,从而导致应用程序读取的值与实际变量值不一致(从角度来看)在上述模式示例中,主线程的寄存器为false,但是子线程已修改为true)。

根据上述情况,我们发现主线程主函数和子线程线程均在变量标志上运行。这时,我们说变量标志是程之间共享数据。主内存(即系统内存不是程序本身所需的内存)标志变量应该对所有共享此变量的线程可见。

volatile 内存可见性_volatile内存模型_volatile 内存屏障

那么,此时,如何在Java中实现线程之间共享数据的内存可见性?这是我们今天需要解释的关键字:volatile。 [Ps:还有其他解决方案可以解决,例如同步锁]

易失关键字

可变中文的意思:多变;不稳定

Volatile关键字是一种类型修饰符,使用它声明的变量没有编译器的未知因素就无法更改。当编译器在编译过程中遇到此关键字声明的变量时,它将不再优化访问该变量的代码,因此可以提供一个特殊地址来确保稳定的访问。

受欢迎的理解:当JVM遇到由该关键字修改的变量时,它将不允许编译器和处理器重新排列指令序列(默认情况下,为了优化性能,JVM允许编译器和处理器重新排列)。

JVM为编译器指定的易失性规则表:

编辑

用volatile修改标志后,运行程序并在运行后检查结果:

volatile内存模型_volatile 内存可见性_volatile 内存屏障

编辑

我们可以看到主线程输入===,子线程也将当前标志输出为true。解释挥发物的作用。

易失性关键字和同步关键字之间的区别

1:Volatile是一种轻量级的同步策略;同步是重量级的;

2:易失性不是互斥的,同步是互斥的;

3:易失性不能保证变量的原子性。

易失性使用场景的要求

使用volatile时需要满足以下两个条件:

1:对变量的写操作不能取决于当前值。

例如,当上述标志值更改为true时,它将不受当前标志值的影响

volatile内存模型_volatile 内存可见性_volatile 内存屏障

2:该变量不能与其他变量一起包含在不变式中。

例如int i; y = i + 1;这种情况是不允许的。该变量不能被其他变量用作不变变量。

仅当状态真正独立于程序中的其他内容时,才可以使用易失性。

适用于方案一:状态标志

方案2:具有较低开销的读写锁定策略

方案3:在单例中再次检查

摘要

当多线程操作共享数据时,Volatile可以解决内存可见性问题。

简单理解:对于由volatile修改的变量,编译器不会优化调用该变量的程序(即,不会将变量放入调用程序的寄存器中),并且将从主内存实时。获取最新数据。

凯的个人博客:

编辑


本文来自电脑杂谈,转载请注明本文网址:
http://www.pc-fly.com/a/shoujiruanjian/article-349890-1.html

    相关阅读
      发表评论  请自觉遵守互联网相关的政策法规,严禁发布、暴力、反动的言论

      热点图片
      拼命载入中...