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及开源框架中随处可见这个关键字,但并发专 ...
随机推荐
- unsupported operand type(s) for +: 'function' and 'str'
unsupported operand type(s) for +: 'function' and 'str' 报错解释:这个错误表明你尝试将一个函数和一个字符串进行加法操作,在Python中,加法不 ...
- 如何更改.NET中的默认时区?
除了"在操作系统中修改时区信息,然后重启.NET应用程序,使其生效"之外.如何在不修改操作系统时区的前提下,修改.NET中的默认时区呢? 这是一位 同学兼同事 于5月21日在技术群 ...
- 洛谷 P4913 二叉树深度
题目链接:二叉树深度 思路 存储二叉树的各个节点并递归搜索二叉树深度. 题解 #include <bits/stdc++.h> using namespace std; #define l ...
- Windows无法访问vsftpd
在搭建vsftpd的时候注意放行相应的服务,注意,是服务,不是端口!! 如果你简单的--add-port放行20和21端口,那么恭喜你,就是访问不了. 正确的方法是--add-service=ftp, ...
- Freertos学习:02-FreeRTOSConfig.h
--- title: rtos-freertos-02-FreeRTOSConfig.h EntryName: rtos-freertos-02-FreeRTOSConfig date: 2020-0 ...
- 嵌入式入门必看!调试工具安装——基于 AM64x核心板
本章节内容是为评估板串口安装USB转串口驱动程序.驱动适用于CH340.CH341等USB转串口芯片. USB转串口驱动安装 适用安装环境:Windows 7 64bit.Windows 10 64b ...
- SQLCel匹配原数据信息,更新原数据所有信息并插入新数据的过程
使用SQLCel高效率(速度快,数据完整)的解决了我领导提的问题 "如何更新数据库中原有的数据并插入新的订单数据" 过程如下: 思路:使用字段匹配和修改字段即可解决问题,用时3分钟 ...
- vue - ES6模块化、promise、webpack打包(所在在学的朋友们先看这篇,看了不吃亏)
首先我要说明一下,没错,还是没有进入vue,刘备请诸葛亮三次都可以了吧,我这也是第三次了,也绝对是最后一次了,我应经摸透了因为,最后的webpack打包加上一个git学了过后我就去vue了. 为什么要 ...
- Nuxt3 的生命周期和钩子函数(十)
title: Nuxt3 的生命周期和钩子函数(十) date: 2024/6/30 updated: 2024/6/30 author: cmdragon excerpt: 摘要:本文详细介绍了Nu ...
- MinIO使用记录
探索MinIO:高性能.分布式对象存储解决方案 注:本文除代码外多数为AI生成 最近因为有项目需要换成Amazon S3的云存储,所以把之前做过的minio部分做一个记录,后面也会把基于这版改造的S3 ...