`
albeter
  • 浏览: 8264 次
  • 性别: Icon_minigender_1
  • 来自: 广州
社区版块
存档分类
最新评论

volatile的一个有趣的实验

 
阅读更多
public class Volatile {

    public static void main(String[] args) {
        final Volatile volObj = new Volatile();
        Thread t2 = new Thread() {
            public void run() {
                while (true) {
                    volObj.check();
                }
            }
        };
        t2.start();

        Thread t1 = new Thread() {
            public void run() {
                System.out.println(volObj.boolValue);
                while (true) {
                    volObj.swap();
                }
            }
        };
        t1.start();
    }

     boolean boolValue;// use volatile to print "WTF!"

    public void check() {
        if (boolValue == !boolValue)
            System.out.println("WTF!");
    }

    public void swap() {
        try {
            Thread.sleep(100);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        boolValue = !boolValue;
    }

}

以上代码出自网络。

如上代码如果把boolValue用volatile修饰的话,就会打印出WTF。(volatile可以保证任何一个线程在读取该域的时候可以读取到最近被写入的值-- effective java )。
1.原因是 if (boolValue == !boolValue) 并不是一个原子操作,读第二个boolValue的时候这时可能已经被另外一个线程中的swap()方法修改了值。所以打印出"WTF"


2.当没有加volatile修饰boolValue的时候,每个线程的boolValue都是主内存中boolValue的一个拷贝,gvm并不保证何时线程中的boolValue会同步主内存中。在这个例子中,我们可以这样理解,每个线程维护者主内存的boolValue的一个拷贝,它们之间并不影响。所以几乎不会发生打印出"WTF"的情况。

3.如果在代码块中增加synchronized块的话,即使使用volatile修饰boolValue也不会打印出"WTF" ,synchronized(this){}修饰这两段代码,避免了两个线程之间的“交叉”从而不会出现1的情况。

synchronized(this){
if (boolValue == !boolValue)
System.out.println("WTF!");
}

synchronized(this){
 boolValue = !boolValue;
}


volatile修饰符不执行互斥访问,但是它可以保证任何一个线程在读取该域的时候可以读取到最近被写入的值。---effective java
分享到:
评论

相关推荐

    Volatile详解,深入学习Volatile

    Volatile是C/C++编程语言中的一个关键字,它与const一起被称为"cv特性",用于指示变量的值可能被系统或其他线程/进程改变,从而强制编译器每次从内存中读取该变量的最新值。在多线程或嵌入式编程中,volatile的作用...

    stm32 volatile变量的正确使用

    例如,在一个任务中修改了一个共享变量,而在另一个任务中使用这个变量时,如果没有使用`volatile`,编译器可能会出于性能考虑将这个变量的值缓存在寄存器中,从而导致读取的是过时的数据。 3. **中断服务程序中的...

    volatile的用法讲解

    2. 一个中断服务子程序中会访问到的非自动变量(Non-automatic variables):在中断服务子程序中,变量的值可能会被改变,因此需要使用volatile修饰符来确保编译器每次都读取最新的值。 3. 多线程应用中被几个任务...

    volatile用法

    `volatile`关键字在C语言中是一个非常重要的概念,主要用于处理多线程环境或者与硬件交互时的内存可见性问题。它的主要作用是确保对变量的修改能够立即反映到所有线程,防止编译器进行不必要的优化,使得其他线程...

    volatile源码分析1

    Java中的volatile关键字是一个关键的同步机制,它在多线程编程中扮演着重要的角色。在面试和技术讨论中,volatile经常成为焦点,但其工作原理却常常引发争议。本文将从JVM、C++以及汇编语言的角度深入探讨volatile的...

    volatile的使用方法

    在这个例子中,我们定义了一个 volatile 的整数变量 i,然后对其进行赋值操作,但是编译器并没有对其进行优化,而是按照我们编写的代码来执行。在第二个例子中,我们可以看到,如果不使用 volatile 关键字,编译器...

    const和volatile分析

    2. 多线程编程:在多线程环境下,当一个变量可能被其他线程修改时,应使用`volatile`,让编译器知道这个变量的值可能会在不通过程序控制的情况下发生变化。 3. 实时系统:在实时系统中,`volatile`用于声明受外部...

    volatile详解

    1. **const与volatile的结合使用**:一个变量可以同时声明为`const`和`volatile`。例如,只读的状态寄存器可以被声明为`const volatile int statusRegister;`。这里的`const`表明程序不应尝试修改这个寄存器的值,而...

    volatile的用法

    Volatile是C语言中的一个类型修饰符,用于告诉编译器该变量可能会在程序的控制之外被改变,从而禁止编译器对涉及该变量的代码做优化处理。这种用法在多线程、中断服务程序和硬件访问等场合特别重要。接下来详细说明...

    单片机中volatile定义的作用

    }答案是这段代码的目的是用来返指针*ptr指向值的平方,但是,由于*ptr指向一个volatile型参数,编译器将产生类似下面的代码:intsquare(volatile int*ptr){int a,b;a=*ptr;b=*ptr;return a*b;}由于*ptr的值可能被...

    volatile 变量的说明

    1. **可见性**:当一个线程修改了volatile变量的值,其他线程能够立即看到修改。这意味着volatile变量的修改对于所有线程都是可见的,避免了数据不一致的问题。在多线程环境下,如果多个线程共享一个变量,并且这个...

    Java线程:volatile关键字

    volatile 变量可用于提供线程安全,但是只能应用于非常有限的一组用例:多个变量之间或者某个变量的当前值与修改后值之间没有约束。 正确使用 volatile 变量的条件是:对变量的写操作不依赖于当前值,以及该变量...

    单片机C语言中volatile的作用

    `volatile`是一个用于声明变量的关键字,在C语言中,使用`volatile`修饰的变量表明其值可能会在没有程序控制的情况下发生改变。这意味着编译器在处理这类变量时不能做任何优化,每次使用时都需要从内存中重新读取其...

    C#中volatile与lock用法

    volatile是C#中用于控制同步的关键字,其意义是针对程序中一些敏感数据,不允许多线程同时访问,保证数据在任何访问时刻,最多有一个线程访问,以保证数据的完整性,volatile是修饰变量的修饰符。 1、volatile的使用...

    C中volatile_const解析

    - 当一个变量被声明为`volatile`时,意味着编译器在使用这个变量时不能假设它的值是不变的。 - 每次访问`volatile`变量时,编译器都会确保从内存中重新加载该变量的值,而不是使用寄存器中的备份。 - 这有助于防止...

    static,const,volatile用法

    - 如果一个变量可能被多个线程同时访问并修改,则应该将其声明为 `volatile` 类型,以确保编译器不会对该变量进行优化而忽略其实际变化。 - **硬件接口**: - 当一个变量代表了硬件寄存器的状态时,如果硬件可能会...

    volatile的作用

    当多个线程访问同一个变量时,为了保证数据的一致性和可见性,可以使用`volatile`关键字。例如,在多线程环境中,如果一个线程修改了一个变量,而另一个线程需要读取这个变量,那么必须确保读取到的是最新的值。`...

Global site tag (gtag.js) - Google Analytics