2 learningcsdn learningcsdn 于 2016.02.29 17:50 提问

volatile 关键字 作用结果求解惑
 public class testVolatile {
    private  int i = 0;

    // a线程调用
    public void foo1() {
        try {
            while (true) {
                Thread.sleep(10);
                System.out.println("第一个:" + i);
                i++;
            }
        } catch (InterruptedException e) {
            // not to do;
        }
    }

    // b线程调用
    public void foo2() {
        try {
            while (true) {
                Thread.sleep(10);
                System.out.println("第二个:" + i);
            }
        } catch (InterruptedException e) {
            // not to do;
        }

    }

    public static void main(String[] args) {

        final testVolatile test = new testVolatile();
        // 线程1
        new Thread() {
            public void run() {
                test.foo1();
            }
        }.start();
        // 线程2
        new Thread() {
            public void run() {
                test.foo2();
            }
        }.start();

    }
}

输出结果如下:

 第一个:0
第二个:1
第一个:1
第二个:2
第一个:2
第二个:3
第一个:3
第二个:4
第一个:4
第二个:5
第一个:5
第二个:6
第一个:6
第二个:7
第一个:7
第二个:8
第一个:8
第二个:9
第一个:9
第二个:10
第一个:10

变量i增加volatile 关键字后如下

 第二个:0
第一个:0
第二个:1
第一个:1
第二个:2
第一个:2
第二个:3
第一个:3
第二个:4
第一个:4
第二个:5
第一个:5
第二个:6
第一个:6
第二个:7
第一个:7
第二个:8
第一个:8
第二个:9
第一个:9
第二个:10

求高人指点,变量 i 没有增加 volatile 关键字时,第二个输出为什么会随着第一个i 的变化而变化?

2个回答

wojiushiwo945you
wojiushiwo945you   Ds   Rxr 2016.02.29 18:43
已采纳

你需要了解volatile关键字作用,一个定义为volatile的变量,它将具备两种性质:第一是保证此变量对所有线程的可见性,即当一个线程修改了这个变量后,这个新值对于其他线程来说是立即可见的。第二就是保证不进行指令重排序。
所以,你没有添加volatile关键字,多线程同时修改变量可能某个线程读到的数据不是最新值,即你的第一个输出结果体现了某个时刻线程1,2同时读到了数值1时,此时线程2可能已经修改了变量。所以导致了不正确的结果。

learningcsdn
learningcsdn 不好意思,回车按多了,,,对于你说的第二不能进行指令重排序,不是很清楚,能进一步解释下吗?
2 年多之前 回复
learningcsdn
learningcsdn 嗯嗯,感谢回答,今天又学习了下,总结来说就是volatile关键字会把一个线程对其的修改立刻回写到内存,并使其它线程的缓存失效,进而其它线程会从内存读取这个变量,此机制来实现对其它线程的可见性。但是此关键字不是原子性的,因此并不能保证线程安全。
2 年多之前 回复
learningcsdn
learningcsdn 嗯嗯,感谢回答,今天又学习了下,总结来说就是volatile关键字会把一个线程对其的修改立刻回写到内存,并使其它线程的缓存失效,进而其它线程会从内存读取这个变量,此机制来实现对其它线程的可见性。但是此关键字不是原子性的,因此并不能保证线程安全。
2 年多之前 回复
learningcsdn
learningcsdn 嗯嗯,感谢回答,今天又学习了下,总结来说就是volatile关键字会把一个线程对其的修改立刻回写到内存,并使其它线程的缓存失效,进而其它线程会从内存读取这个变量,此机制来实现对其它线程的可见性。但是此关键字不是原子性的,因此并不能保证线程安全。
2 年多之前 回复
learningcsdn
learningcsdn 嗯嗯,感谢回答,今天又学习了下,总结来说就是volatile关键字会把一个线程对其的修改立刻回写到内存,并使其它线程的缓存失效,进而其它线程会从内存读取这个变量,此机制来实现对其它线程的可见性。但是此关键字不是原子性的,因此并不能保证线程安全。
2 年多之前 回复
learningcsdn
learningcsdn 嗯嗯,感谢回答,今天又学习了下,总结来说就是volatile关键字会把一个线程对其的修改立刻回写到内存,并使其它线程的缓存失效,进而其它线程会从内存读取这个变量,此机制来实现对其它线程的可见性。但是此关键字不是原子性的,因此并不能保证线程安全。
2 年多之前 回复
learningcsdn
learningcsdn 嗯嗯,感谢回答,今天又学习了下,总结来说就是volatile关键字会把一个线程对其的修改立刻回写到内存,并使其它线程的缓存失效,进而其它线程会从内存读取这个变量,此机制来实现对其它线程的可见性。但是此关键字不是原子性的,因此并不能保证线程安全。
2 年多之前 回复
wojiushiwo945you
wojiushiwo945you   Ds   Rxr 2016.03.01 10:17

指令重排:是指我们的代码的执行顺序可能跟它们的编写顺序不一致,因为java编译器在编译过程中会进行代码优化,而提前执行某些语句。
使用这个关键字就可以禁止编译器对该变量的操作代码进行重排优化,保证代码的执行顺序。而普通变量就不能保证了。

learningcsdn
learningcsdn 嗯嗯,明白了,多谢多谢
2 年多之前 回复
Csdn user default icon
上传中...
上传图片
插入图片
准确详细的回答,更有利于被提问者采纳,从而获得C币。复制、灌水、广告等回答会被删除,是时候展现真正的技术了!
其他相关推荐
volatile关键字及其作用
概述:本文主要介绍Java语言中的volatile关键字,内容涵盖volatile的保证内存可见性、禁止指令重排等。
C语言关键字static和volatile 的含义和作用
C语言关键字static和volatile 的含义和作用
浅谈volatile关键字的作用
1、volatile关键字的作用是什么? 多线程中的原子性、可见性、有序性分别表示什么意思? volatile关键字的作用: volatile是java中的一个类型修饰符。它是被设计用来修饰被不同线程访问和修改的变量。如果不加入volatile,基本上会导致这样的结果:要么无法编写多线程程序,要么编译器失去大量优化的机会。 可见性:就是指当一个线程修改了线程共享变量的值,其它
java中的volatile关键字的功能详解
Cookie的应用场景: 1,记录用户的登陆状态,提示用户是否记住密码; 2,购物车购物功能; 我们知道,在web开发过程中,我们都要和cookie打交道,有时候离开了cookie还真玩不转。cookie最典型的应用莫过于登陆提示,最近在做一个小项目,正好要用到cookie的知识,在这里顺便做一下总结。
Java 关键字volatile 与 synchronized 作用与区别
1,volatile    volatile告诉jvm, 它所修饰的变量不保留拷贝,直接访问主内存中的。   在Java内存模型中,有main memory,每个线程也有自己的memory (例如寄存器)。为了性能,一个线程会在自己的memory中保持要访问的变量的副本。这样就会出现同一个变量在某个瞬间,在一个线程的memory中的值可能与另外一个线程memory中的值,或者main memo
关键字volatile的含义及使用
volatile的本意是“易变的” C语言书籍这样定义volatile关键字:volatile提醒编译器它后面所定义的变量随时都有可能改变,因此编译后的程序每次需要存储或读取这个变量的时候,都会直接从变量地址中读取数据。。如果没有volatile关键字,则编译器可能优化读取和存储,可能暂时使用寄存器中的值,如果这个变量由别的程序更新了的话,将出现不一致的现象。 文章出自:http://bbs.
关键字volatile的作用和三个不同的应用场合
学习C关键词的时候,我们看到了一个新面孔——volatile。在程序员面试宝典中提到“关键字volatile的面试例题是考查嵌入式编程”,中间有一段解析: 回答不出这个问题的人是不会被雇佣的。我认为这是区分C程序员和嵌入式系统程序员的最基本的问题。搞嵌入式的家伙们经常同硬件、中断、RTOS等等打交道,所有这些都要求用到volatile变量。不懂得volatile的内容将会带来灾难。 假设被面
C++中的关键字 volatile 详解
突然想到一个解释volatile关键字的很好的例子。就当做引子,来讲一讲这个关键字吧。 const int iNum = 0; int *iPtr = const_cast(&iNum); *iPtr = 5; cout << "iNum = "<< iNum << endl; cout << "*iPtr = " << *iPtr << endl; cout << "addr iNum: "
Linux中volatile关键字的作用
一.前言 1.编译器优化介绍: 由于内存访问速度远不及CPU处理速度,为提高机器整体性能,在硬件上引入硬件高速缓存Cache,加速对内存的访问。另外在现代CPU中指令的执行并不一定严格按照顺序执行,没有相关性的指令可以乱序执行,以充分利用CPU的指令流水线,提高执行速度。以上是硬件级别的优化。再看软件一级的优化:一种是在编写代码时由程序员优化,另一种是由编译器进行优化。编译器优化常用的方法有:
多线程---volatile关键字
在多线程中,volatile关键字是很重要的一个知识点,在多线程共享资源的时候,每个线程数据对外都是不可见的,这就容易出现”脏读”现象,其实就是线程私有堆栈中的数据和公共堆栈中的数据不同步造成的.解决这样的问题,就要使用volatile关键字了。 内存结构 有这个结构图,就能很清晰的知道为毛会造成数据的不同步了。每个线程都会有各自的线程栈,执行运算的时候,是从公共堆栈读取数据到线程堆栈中,线程