volatile重要特性-可见性,避免指令重排序-案例讲解
1.背景
volatile 修饰的作用????
什么是可见性??
什么是指令重排序??
2.可见性-案例
package com.my.aqs; /**
* @Copyright (C) XXXXX技有限公司
* @Author: ldp
* @Date: 2023/4/28 9:10
* @Description: <p>
* volatile 的可见性代码演示
* </p>
*/
public class Volatile021Demo {
// 如果a 没有 被 volatile 修饰,这里的a是 [不可见的] ,[不可以] 读取到其他线下修改后的值, 即从[工作]内存中读取==> 产生死循环
// 如果a 被 volatile 修饰,这里的a是 [可见的] ,[可以]读取到其他线下修改后的值, 即从[主]内存中读取 ==> 不会产生死循环
// static volatile int a, b;
static int a, b; /**
* 指令重排序测试
*
* @param args
*/
public static void main(String[] args) throws InterruptedException {
// 线程A
Thread threadA = new Thread(() -> {
a = 1;
System.out.println("A执行完成:" + a);
});
// 线程B
Thread threadB = new Thread(() -> {
// 如果a 没有 被 volatile 修饰,这里的a是 [不可见的] ,[不可以] 读取到其他线下修改后的值, 即从[工作]内存中读取==> 产生死循环
// 如果a 被 volatile 修饰,这里的a是 [可见的] ,[可以]读取到其他线下修改后的值, 即从[主]内存中读取 ==> 不会产生死循环
while (a == 0) {
try {
// System.out.println("等待中===="); // 就算不添加volatile 修饰a, 执行输出语句后a会重新从主内存中读取
// System.out.println("当前a==>:" + a);
// Thread.sleep(500);// 就算不添加volatile 修饰a, 执行输sleep后a会重新从主内存中读取
b = a; // 不会导致从主内存中读取
} catch (Exception e) {
e.printStackTrace();
}
}
System.out.println("B执行完成:" + a);
});
threadB.start();
// 让B线程先执行
Thread.sleep(50);
threadA.start();
while (threadA.isAlive() || threadB.isAlive()) {
}
System.out.println("main执行完成:" + a);
}
}
3.避免指令重排序-案例
package com.my.aqs; import java.util.HashSet;
import java.util.Set; /**
* @Copyright (C) XXXXX技有限公司
* @Author: ldp
* @Date: 2023/4/28 15:03
* @Description:
*/
public class Volatile03Demo {
// static volatile int a, b, A, B;
static int a, b, c, d; /**
* 指令重排序-案例演示
* <p>
* 如果:下面的代码,如果不考虑 指令重排序的问题, c和d永远都不会同时为0;
* 但是:因为在没有volatile修饰的情况下,可能会产生指令重排序,因此会产生 指令重排序,
* 导致
* t1线程中先执行 c = b;
* t2线程中先执行 d = a;
* 这两行代码先执行,从而导致c 和 d同时为0;
*
* @param args
* @throws InterruptedException
*/
public static void main(String[] args) throws InterruptedException {
long num = 0;
Set<String> ABSet = new HashSet<>(8);
while (true) {
num++;
a = 0;
b = 0;
c = 0;
d = 0;
Thread t1 = new Thread(() -> {
a = 1;
c = b;
});
Thread t2 = new Thread(() -> {
b = 1;
d = a;
});
t1.start();
t2.start();
t1.join();
t2.join();
ABSet.add("a=" + a + "|b=" + b + "|c=" + c + "|d=" + d);
if (c == 0 && d == 0) {
System.out.println("a=" + a + "|b=" + b + "|c=" + c + "|d=" + d);
System.out.println("num=" + num);
System.out.println(ABSet);
break;
}
}
}
}
完美!
volatile重要特性-可见性,避免指令重排序-案例讲解的更多相关文章
- JVM并发机制的探讨——内存模型、内存可见性和指令重排序
并发本来就是个有意思的问题,尤其是现在又流行这么一句话:“高帅富加机器,穷矮搓搞优化”. 从这句话可以看到,无论是高帅富还是穷矮搓都需要深入理解并发编程,高帅富加多了机器,需要协调多台机器或者多个CP ...
- 轻松学JVM(二)——内存模型、可见性、指令重排序
上一篇我们介绍了JVM的基本运行流程以及内存结构,对JVM有了初步的认识,这篇文章我们将根据JVM的内存模型探索java当中变量的可见性以及不同的java指令在并发时可能发生的指令重排序的情况. 内存 ...
- JVM学习--(二)内存模型、可见性、指令重排序
我们将根据JVM的内存模型探索java当中变量的可见性以及不同的java指令在并发时可能发生的指令重排序的情况. 内存模型 首先我们思考一下一个java线程要向另外一个线程进行通信,应该怎么做,我们再 ...
- 深入理解JVM(二)——内存模型、可见性、指令重排序
上一篇我们介绍了JVM的基本运行流程以及内存结构,对JVM有了初步的认识,这篇文章我们将根据JVM的内存模型探索java当中变量的可见性以及不同的java指令在并发时可能发生的指令重排序的情况. 内存 ...
- 深入理解JVM一内存模型、可见性、指令重排序
一.内存模型 首先我们思考一下一个java线程要向另外一个线程进行通信,应该怎么做,我们再把需求明确一点,一个java线程对一个变量的更新怎么通知到另外一个线程呢?我们知道java当中的实例对象.数组 ...
- 内存可见性,指令重排序,JIT。。。。。。从一个知乎问题谈起
在知乎上看到一个问题<java中volatile关键字的疑惑?>,引起了我的兴趣 问题是这样的: package com.cc.test.volatileTest; public clas ...
- 关于volatile的可见性和禁止指令重排序的疑惑
在学习volatile语义的可见性和禁止指令重排序的相关测试中,发现并不能体现出禁止指令重排序的特性 实验代码如下 package com.aaron.beginner.multithread.vol ...
- 使用 volatile 关键字保证变量可见性和禁止指令重排序
volatile 概述 volatile 是 Java 提供的一种轻量级的同步机制.相比于传统的 synchronize,虽然 volatile 能实现的同步性要差一些,但开销更低,因为它不会引起频繁 ...
- Java的多线程机制系列:不得不提的volatile及指令重排序(happen-before)
一.不得不提的volatile volatile是个很老的关键字,几乎伴随着JDK的诞生而诞生,我们都知道这个关键字,但又不太清楚什么时候会使用它:我们在JDK及开源框架中随处可见这个关键字,但并发专 ...
- Java的多线程机制系列:(四)不得不提的volatile及指令重排序(happen-before)
一.不得不提的volatile volatile是个很老的关键字,几乎伴随着JDK的诞生而诞生,我们都知道这个关键字,但又不太清楚什么时候会使用它:我们在JDK及开源框架中随处可见这个关键字,但并发专 ...
随机推荐
- Mysql性能优化(详解)
引言 今天,数据库的操作越来越成为整个应用的性能瓶颈了,这点对于Web应用尤其明显.关于数据库的性能,这并不只是DBA才需要担心的事,而这更是我们程序员需要去关注的事情.当我们去设计数据库表结构,对操 ...
- 洛谷 P5595 歌唱比赛
题目链接:歌唱比赛 思路 根据题目分析可得,假如小x的点赞数是123111,小y的点赞数是234111,则字符串的第4为到第6位结果都为Z,分别为对比(111,111),(11,11),(1,1),字 ...
- STM32的内存管理(转)
背景 这里针对STM32F407芯片+1M外部内存的内存管理!(全篇是个人愚见,如果错误,请不吝指出!) 定义 首先,定义3个内存池,分别是内部SRAM,外表SRAM和CCM:通过指定内存中的绝对地址 ...
- React Router 6
路由的概念,可以想像一下路由器,当来了一个请求时,路由器做了什么事情?它会把请求的IP地址和路由表进行匹配,匹配成功后,进行转发,直到目标主机.可以看到路由有三部分组成,一个是请求,一个是路由表,一个 ...
- 「Pygors跨平台GUI」2:安装MinGW-w64、MSYS2还是WSL2
「Pygors系列」一句话导读: MinGW-w64只有编译器,MSYS2带着更新环境,WSL2实用性比较高 历史与渊源 Windows平台 Linux平台 二进制兼容 WSL2:运行Linux程 ...
- 4. 系统I/O
系统 I/O 示例代码: #include <iostream> // 标准库头文件 // #include "myheader.h" // 自己写的头文件 void ...
- 2. C++的编译/链接模型
C++的编译/链接模型 简单的加工模型 问题:无法处理大型程序 加工耗时较长 即使少量修改,也需要重新加工 解决方案:分块处理 好处 编译消耗资源,但一次处理输入较少 链接程序较多,但处理速度较快 便 ...
- 基于Java+SpringBoot+Vue宠物咖啡馆平台设计和实现
\n文末获取源码联系 感兴趣的可以先收藏起来,大家在毕设选题,项目以及论文编写等相关问题都可以给我加好友咨询 系统介绍: 随着信息技术在管理上越来越深入而广泛的应用,管理信息系统的实施在技术上已逐步成 ...
- [oeasy]python00134_[趣味拓展]python起源_历史_Guido人生_ABC编程语言_Tanenbaum
python 历史 回忆上次内容 颜文字是kaomoji 把字符变成一种图画的方法 一层叠一层 很多好玩儿的kaomoji是一层层堆叠起来的meme 添加图片注释,不超过 140 字(可选 ...
- vue项目锚点定位+滚动定位
功能: HTML: js: scrollEvent(e) { let scrollItems = document.querySelectorAll('.condition-container') f ...