关于volatile的可见性和禁止指令重排序的疑惑
在学习volatile语义的可见性和禁止指令重排序的相关测试中,发现并不能体现出禁止指令重排序的特性
实验代码如下
package com.aaron.beginner.multithread.volatiletest; import java.util.concurrent.CountDownLatch; /**
* @author
* @description 一句话描述该文件的用途
* @date 2017-03-01
*/
public class VolatileAndNonVolatileTest
{ private volatile boolean flag; private int num; public static void main(String[] args) throws InterruptedException
{ for (int i = 0; i < 5000; i++)
{
final VolatileAndNonVolatileTest test = new VolatileAndNonVolatileTest(); CountDownLatch latch = new CountDownLatch(2);
Thread write = new Thread(() ->
{
test.write();
latch.countDown();
}); Thread read = new Thread(() ->
{
test.read();
latch.countDown();
}); write.start();
read.start(); latch.await();
}
} private void read()
{
if (flag)
{
System.out.println("=" + num * num);
}
} private void write()
{
num = 10;//步骤1 flag = true;//步骤2 } }
实验步骤:
注意关注代码中flag变量,会分别测试flag变量有volatile修饰和没有volatile修饰时的输出情况
本测试代码主要的功能:
- write方法负责修改num变量,修改后设置flag=true,表示num变量已经修改成功
- read方法负责读取修改后的num值,并输入平方
实验步骤:
- 在循环中每次启动两个线程,一个线程负责调用write修改数据,另一个线程负责读取修改后的值
- 观察实验结构
预期结果:
- 当flag没有volatile修饰的时候,我们本应该期望的是能够输出"=100"
- 当flag有volatile修饰的时候,由于有可见性和禁止了指令重排序,每次正常输出"=100"
实际结果:
- 当flag没有volatile修饰的时候,多次实验均没有发现指令重排序发生(即出现"=0",也就是说write方法中步骤1和步骤2没有发生重排序(步骤2比步骤1先发生))
- 当flag有volatile修饰的时候(理论上有可见性和禁止了指令重排序,不会出现"=0"),实际上也没有出现"=0",和1结果一致。
即加了和没加volatile的结果是一致的
试问各位大神,有知道怎么测试这个volatile,体现禁止了指令重排序的特点和可见性的特点吗?
关于volatile的可见性和禁止指令重排序的疑惑的更多相关文章
- 使用 volatile 关键字保证变量可见性和禁止指令重排序
volatile 概述 volatile 是 Java 提供的一种轻量级的同步机制.相比于传统的 synchronize,虽然 volatile 能实现的同步性要差一些,但开销更低,因为它不会引起频繁 ...
- Volatile禁止指令重排序(三)
Volatile禁止指令重排 计算机在执行程序时,为了提高性能,编译器和处理器常常会对指令重排,一般分为以下三种: 源代码 -> 编译器优化的重排 -> 指令并行的重排 -> 内存系 ...
- 单例模式+volatile禁止指令重排序
单例模式: 单例,顾名思义就是只能有一个.不能再出现第二个.就如同地球上没有两片一模一样的树叶一样. 在这里就是说:一个类只能有一个实例,并且整个项目系统都能访问该实例. 单例模式共分为两大类: 懒汉 ...
- Java并发编程-线程可见性&线程封闭&指令重排序
一.指令重排序 例子如下: public class Visibility1 { public static boolean ready; public static int number; } pu ...
- synchronized无法禁止指令重排序的证明
package demo.reorder; import java.util.concurrent.ExecutorService; import java.util.concurrent.Execu ...
- Java的多线程机制系列:不得不提的volatile及指令重排序(happen-before)
一.不得不提的volatile volatile是个很老的关键字,几乎伴随着JDK的诞生而诞生,我们都知道这个关键字,但又不太清楚什么时候会使用它:我们在JDK及开源框架中随处可见这个关键字,但并发专 ...
- Java的多线程机制系列:(四)不得不提的volatile及指令重排序(happen-before)
一.不得不提的volatile volatile是个很老的关键字,几乎伴随着JDK的诞生而诞生,我们都知道这个关键字,但又不太清楚什么时候会使用它:我们在JDK及开源框架中随处可见这个关键字,但并发专 ...
- 不得不提的volatile及指令重排序(happen-before)
微信公众号[程序员江湖] 作者黄小斜,斜杠青年,某985硕士,阿里 Java 研发工程师,于 2018 年秋招拿到 BAT 头条.网易.滴滴等 8 个大厂 offer,目前致力于分享这几年的学习经验. ...
- 指令重排序所带来的问题及使用volatile关键字解决问题
首先看下如下代码: 指令重排序和优化后代码如下:if(!stop)while(true){}volatile最适合使用的是一个线程写.其他线程读的场合,如果有多个线程并发写操作,仍然需要使用锁或者线程 ...
随机推荐
- ora-12154
64位oracle,32位pl/sql pl/sql配置完之后,一直报错: ora-12154 配置环境变量ORACLE_HOME:D:\softInstrall\oracle\product\11. ...
- Mysql 多列形成主键(复合主键 )
什么是数据表的复合主键 所谓的复合主键 就是指你表的主键含有一个以上的字段组成 比如 create table test ( name varchar(19), id number, ...
- JAVA 遍历文件夹下的所有文件(递归调用和非递归调用)
JAVA 遍历文件夹下的所有文件(递归调用和非递归调用) 1.不使用递归的方法调用. public void traverseFolder1(String path) { int fileNum = ...
- PHP文件上传和文件操作案例
<?php /* *文件配置变量$dirname是目录名称 */ session_start(); $dirname = 'upload'; $fileClass = new fileClass ...
- php redis 函数手册
Redis::__construct构造函数$redis = new Redis();connect, open 链接redis服务参数host: string,服务地址port: int,端口号ti ...
- 怎样看paper 最有效率
thinking more after reading. Don't just read the papers.in addition, at begining, you'd better focus ...
- jQuery插件开发详解
我们该如何扩展jQuery呢?主要可以通过下面2个来扩展:$.extend 和 $.fn $.extend如果把jQuery当成一个类,$.extend相当于为该类添加了静态方法extend. < ...
- linux iptables 配置
1.查看已有配置 iptables -L -n 2.清除原有规则. iptables -F 清除预设表filter中的所有规则链的规则 iptables -X 清除预设表f ...
- MySQL生产库全库备份脚本
创建一个单独的备份用户backup,不要用root 创建备份目录 :mkdir -p /databackup/fullbackup mysql> grant SELECT,RELOAD,SHOW ...
- List与Linkedlist、Arrylist、Vector、Map应用
1.List与LinkedList List是数组链表 LinkedList是指针链表 选择List还是LinkedList要看你的使用特点. 数组链表访问快,复 ...