Java多线程编程中的volatile关键字

在讲解之前先来看一个例子

package org.MyVolatile;

public class MyVolatile {

    public static void main(String[] args) {
        // TODO Auto-generated method stub
        TestVolatile testVolatile = new TestVolatile();
        testVolatile.start();
        try {
            Thread.sleep(100);
        } catch (Exception e) {
            // TODO: handle exception
        }
        System.out.println("主线程设置flag为false");
        testVolatile.setFlag(false);
    }
}


class TestVolatile extends Thread{

     private boolean flag = true;

    @Override
    public void run() {
        System.out.println("执行线程");

        while(true) {
            if(!flag) {
                break;
            }
        }
        System.out.println("退出线程");

    }
    public void setFlag(boolean flag) {
        this.flag = flag;
    }   
}

线程执行体中当flag设置为false时,线程便会结束执行.
在主线程里将flag设置为false.但是结果却令人意外.
输出

执行线程
主线程设置flag为false

也就是说线程中的循环并没有结束执行,还在运行.
解决
使用volatile 修饰flag.

 volatile private boolean flag = true;

重新执行
输出

执行线程
主线程设置flag为false
退出线程

也就是加了volatile后,程序终于按照我们所想的逻辑实现了.
原因
这里写图片描述
JVM在创建每一个线程时,都会给该线程创建一个私有堆栈,造成上述问题的原因是私有堆栈中的值和公有堆栈中的值不同步造成的.解决这个问题就需要使用volatile.当线程访问被volatile修饰的变量时,会强制从公有堆栈中获取值.

synchronized和volatile比较
1.关键字volatile是线程同步的轻量级表现,所以volatile的性能肯定比synchronized要好.
2.volatile只能修饰变量,而synchronized可以修饰方法和语句块.
3.多线程访问volatile变量不会发生阻塞,但是访问synchronized修饰的方法和语句块会发生阻塞.
4.volatile只能保证多线程间数据的可见性,并不能保证原子性与安全性.
  而synchronized可以保证原子性,可见性,安全性.
5.volatile解决的是多线程间的可见性,而synchronized解决的是多线程之间访问资源的同步性.

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值