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。([color=red]volatile可以保证任何一个线程在读取该域的时候可以读取到最近被写入的值-- effective java [/color])。
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
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值