在学习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修饰时的输出情况

本测试代码主要的功能:

  1. write方法负责修改num变量,修改后设置flag=true,表示num变量已经修改成功
  2. read方法负责读取修改后的num值,并输入平方

实验步骤:

  1. 在循环中每次启动两个线程,一个线程负责调用write修改数据,另一个线程负责读取修改后的值
  2. 观察实验结构

预期结果:

  1. 当flag没有volatile修饰的时候,我们本应该期望的是能够输出"=100"
  2. 当flag有volatile修饰的时候,由于有可见性和禁止了指令重排序,每次正常输出"=100"

实际结果:

  1. 当flag没有volatile修饰的时候,多次实验均没有发现指令重排序发生(即出现"=0",也就是说write方法中步骤1和步骤2没有发生重排序(步骤2比步骤1先发生))
  2. 当flag有volatile修饰的时候(理论上有可见性和禁止了指令重排序,不会出现"=0"),实际上也没有出现"=0",和1结果一致。

  即加了和没加volatile的结果是一致的

试问各位大神,有知道怎么测试这个volatile,体现禁止了指令重排序的特点和可见性的特点吗?

关于volatile的可见性和禁止指令重排序的疑惑的更多相关文章

  1. 使用 volatile 关键字保证变量可见性和禁止指令重排序

    volatile 概述 volatile 是 Java 提供的一种轻量级的同步机制.相比于传统的 synchronize,虽然 volatile 能实现的同步性要差一些,但开销更低,因为它不会引起频繁 ...

  2. Volatile禁止指令重排序(三)

    Volatile禁止指令重排 计算机在执行程序时,为了提高性能,编译器和处理器常常会对指令重排,一般分为以下三种: 源代码 -> 编译器优化的重排 -> 指令并行的重排 -> 内存系 ...

  3. 单例模式+volatile禁止指令重排序

    单例模式: 单例,顾名思义就是只能有一个.不能再出现第二个.就如同地球上没有两片一模一样的树叶一样. 在这里就是说:一个类只能有一个实例,并且整个项目系统都能访问该实例. 单例模式共分为两大类: 懒汉 ...

  4. Java并发编程-线程可见性&线程封闭&指令重排序

    一.指令重排序 例子如下: public class Visibility1 { public static boolean ready; public static int number; } pu ...

  5. synchronized无法禁止指令重排序的证明

    package demo.reorder; import java.util.concurrent.ExecutorService; import java.util.concurrent.Execu ...

  6. Java的多线程机制系列:不得不提的volatile及指令重排序(happen-before)

    一.不得不提的volatile volatile是个很老的关键字,几乎伴随着JDK的诞生而诞生,我们都知道这个关键字,但又不太清楚什么时候会使用它:我们在JDK及开源框架中随处可见这个关键字,但并发专 ...

  7. Java的多线程机制系列:(四)不得不提的volatile及指令重排序(happen-before)

    一.不得不提的volatile volatile是个很老的关键字,几乎伴随着JDK的诞生而诞生,我们都知道这个关键字,但又不太清楚什么时候会使用它:我们在JDK及开源框架中随处可见这个关键字,但并发专 ...

  8. 不得不提的volatile及指令重排序(happen-before)

    微信公众号[程序员江湖] 作者黄小斜,斜杠青年,某985硕士,阿里 Java 研发工程师,于 2018 年秋招拿到 BAT 头条.网易.滴滴等 8 个大厂 offer,目前致力于分享这几年的学习经验. ...

  9. 指令重排序所带来的问题及使用volatile关键字解决问题

    首先看下如下代码: 指令重排序和优化后代码如下:if(!stop)while(true){}volatile最适合使用的是一个线程写.其他线程读的场合,如果有多个线程并发写操作,仍然需要使用锁或者线程 ...

随机推荐

  1. 如何检测 Android Cursor 泄漏

    简介: 本文介绍如何在 Android 检测 Cursor 泄漏的原理以及使用方法,还指出几种常见的出错示例.有一些泄漏在代码中难以察觉,但程序长时间运行后必然会出现异常.同时该方法同样适合于其他需要 ...

  2. bzoj2049

    2049: [Sdoi2008]Cave 洞穴勘测 Time Limit: 10 Sec  Memory Limit: 259 MBSubmit: 7579  Solved: 3548[Submit] ...

  3. apue- chapter 3 文件IO

    1.函数open和函数openat #include<fcnl.h> int open(const char *path,int oflag,.../*mode_t mode */) in ...

  4. 1.1.2.托管对象模型(Core Data 应用程序实践指南)

    托管对象模型即对象图,可以看成实体类的描述,规定了数据字段. 要想创建托管对象模型,需生成NSManagedObjectModel类的实例.

  5. tomcat 修改网站路径(Java之负基础实战)

    1.找到server.xml 在tomcat安装路径/conf/server.xml 2.搜索webapps 添加 <Context path="" docBace=&quo ...

  6. 样式(Style)和主题(Theme)资源——样式资源

    样式和主题资源都是用于对Android应用进行“美化”的,只要充分利用Android应用的样式和主题资源,开发者可以开发出各种风格的Android应用. 样式资源:         如果我们经常需要对 ...

  7. NodeMCU之旅(三):响应配置按钮

    引言 在之前的代码中,要连接的WIFI信息都已写死在代码里,这显然不能适应我们的需求.所以需要想个办法让用户可以配置这些信息. WIFI工作模式 NodeMCU支持STATION,SOFTAP,STA ...

  8. Java Me-List控件的用法案例

    /** * Java Me-List控件的用法案例 */package com.xushouwei.cn; import java.io.IOException;import javax.microe ...

  9. js原生设计模式——8单例模式

    1.单例模式——在js中就是指的单个对象,可用于命名空间声明 2.示例 <!DOCTYPE html><html lang="en"><head> ...

  10. 管理维护Replica Sets

    1.读写分离 有一些第三方的工具,提供了一些可以让数据库进行读写分离的工具.我们现在是否有一个疑问,从库要是能进行查询就更好了,这样可以分担主库的大量的查询请求. 1. 先向主库中插入一条测试数据 2 ...