Voltatile关键字

Voltatile关键字

1.Voltatile是一个轻量级锁,相比重量级锁synchronized,只保证可见性,不保证原子性。
2.Voltatile时修饰共享变量的,synchronized时用来修饰变量的调用者。

  • 内存模型的相关概念

    共享变量:所有实例域、静态域和数组元素存储在堆内存中,堆内存在线程之间共享,说简单点,就是全局变量,静态变量,以及数组,对象等,在多线程中可以称之为共享变量。
    缓存不一致:一个变量在多个CPU中缓存时,当各CPU从高速缓存中更新数据到主存时。

    缓存不一致的解决方案:
    1)通过在总线加LOCK#锁的方式(一个线程访问时上锁,其他线程访问不了,效率低)。
    2)通过缓存一致

  • 并发编程的三大特性
    1.可见性
    只要有一个线程将变量的值改了,马上就会同步到内存,其他的线程马上就可以得到这个改过后的值。
    2.原子性
    我们把一个或者多个操作在CPU执行的过程中不被中断的特性称为原子性,要么同时成功,要么同时失败。但是volatile不保证原子性。
    3.有序性
    有序性指的是程序按照代码的先后顺序执行

  • Java的内存模型(Java Memory Model简称JMM)
    1.JMM定义了Java 虚拟机(JVM)在计算机内存(RAM)中的工作方式。JVM是整个计算机虚拟模型,所以JMM是属于JVM的。
    2.java内存模型中规定所有的变量都存储在主内存,主内存是所有线程都可以访问的空间。但是线程对变量的操作(读取和赋值)都是在自己的工作空间内完成,首先要将变量拷贝到自己的工作空间,然后对变量进行操作,操作完成再将变量写回到主内存。

  • Voltatile关键字的原理和实现机制
    1.Voltatile的特点:
    1)保证内存可见性
    2)不保证原子性
    3)禁止指令重排(保证有序性)
    2.代码加入Voltatile关键字之后,会多出一个lock的前缀指令,相当于一个内存屏障(即解决缓存不一致)
    lock前缀指令:
    1)它确保指令重排序时不会把其后面的指令排到内存屏障之前的位置,也不会把前面的指令排到内存屏障的后面(即在执行到内存屏障这句指令时,在它前面的操作已经全部完成),从而禁止指令重排序
    (1)单线程环境, 重排序能保证程序的最终结果和顺序执行的结果一致
    (2)多线程调度过程中, 由于重排序存在, 两个线程的变量无法保证一致性
    volatile实现了禁止指令重排的优化,从而避免了多线程环境下出现程序乱序执行的现象。

    2)它会强制将对缓存的修改操作立即写入主存,以保证内存可见性

public class TestVolatile {
    public static void main(String[] args) {
        ThreadDemo td = new ThreadDemo();
        new Thread(td).start();
        while (true) {
            if (td.isFlag()) {
                System.out.println("----");
                break;
            }
        }
    }
}
class ThreadDemo implements Runnable {
    // 给变量加上volatile关键字,实现内存可见性
    private volatile boolean flag = false;
    @Override
    public void run() {
        try {
            Thread.sleep(200);
        } catch (InterruptedException e) {
        }
        flag = true;
        System.out.println("flag=" + isFlag());
    }
    public boolean isFlag() {
        return flag;
    }
    public void setFlag(boolean flag) {
        this.flag = flag;
    }
}

当主存中的值改变的时候,可以及时通知其他线程,保证每次能够更新到最新数据

  • 使用Voltatile关键字的场景
    synchronized 关键字是防止多个线程同时执行一段代码,那么就会很影响程序执行效率;而 volatile 关键字在某些情况下性能要优于 synchronized,但是要注意 volatile 关键字是无法替代 synchronized 关键字的,因为 volatile 关键字无法保证操作的原子性。通常来说,使用 volatile 必须具备以下两个条件: 1)对变量的写操作不依赖于当前值;
    2)该变量没有包含在具有其他变量的不变式中。

关键字Voltatile主要适用的场景是:
1.状态标记量

// 示例 1
volatile boolean flag = false;
while(!flag){
    doSomething();
}
public void setFlag() {
    flag = true;
}

用于判断满足某个条件时执行某个事件

// 示例 2
volatile boolean inited = false;
//线程1:
context = loadContext();  
inited = true;            
//线程2:
while(!inited ){
    sleep()
}
doSomethingwithconfig(context);

2.double-check(双重检查)
在使用之前检查数据是否使用过

class Singleton{
    private volatile static Singleton instance = null;

    private Singleton() {

    }

    public static Singleton getInstance() {
        if(instance==null) {
            synchronized (Singleton.class) {
                if(instance==null)
                    instance = new Singleton();
            }
        }
        return instance;
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值