volatile关键字

volatile

volatile是Java中一种比sychronized关键字更轻量级的较弱的同步机制。与sychronized相比,在访问volatile变量时不会执行加锁操作,因此也就不会使执行线程阻塞。volatile 变量所需的编码较少,并且运行时开销也较少。

 

volatile变量具有的特性:

1、可见性:使用volatile可以保证某一个线程对变量的更新对于其他所有线程是可见的。

2、有序性:禁止指令重排序优化,在一定程度上保证了有序性。

3、原子性:volatile没办法保证对变量的操作的原子性。(synchronized和Lock可以)

 

volatile修饰变量var保证可见性的三个步骤:

1、使用volatile关键字会强制将修改的值立即写入主存。

2、当线程2进行修改时,会导致线程1的工作内存中缓存变量var的缓存行无效.

3、由于线程1的工作内存中缓存变量var的缓存行无效,所以线程1再次读取变量var的值时会去主存读取。

也就是说,每次读取volatile修饰的变量都需要从主存中读取,而不是缓存中。

 

禁止指令重排序:

1、当程序执行到volatile变量的读操作或者写操作时,在其前面的操作的更改肯定全部已经进行,且结果已经对后面的操作可见;在其后面的操作肯定还没有进行。

2、在进行指令优化时,不能将在对volatile变量访问的语句放在其后面执行,也不能把volatile变量后面的语句放到其前面执行。

 

使用场景:

1、对变量的写操作不依赖于当前值。

    比如:volatile 变量不能用作线程安全计数器。虽然增量操作(x++)看上去类似一个单独操作,实际上它是一个由(读取-修改-写入)操作序列组成的组合操作,必须以原子方式执行,而 volatile 不能提供必须的原子特性。实现正确的操作需要使x 的值在操作期间保持不变,而 volatile 变量无法实现这点。

2、该变量没有包含在具有其他变量的不变式中。(保证原子性)

   例子:下面是一个非线程安全的数值范围类。它包含了一个不变式 —— 下界总是小于或等于上界。

public class NumberRange {  
    private volatile int lower;
    private volatile int upper;  
  
    public int getLower() { return lower; }  
    public int getUpper() { return upper; }  
  
    public void setLower(int value) {   
        if (value > upper)   
            throw new IllegalArgumentException(...);  
        lower = value;  
    }  
  
    public void setUpper(int value) {   
        if (value < lower)   
            throw new IllegalArgumentException(...);  
        upper = value;  
    }  
}

将 lower 和 upper 字段定义为 volatile 类型不能够充分实现类的线程安全;而仍然需要使用同步——使 setLower()和 setUpper() 操作原子化。

否则,如果凑巧两个线程在同一时间使用不一致的值执行 setLower 和 setUpper 的话,则会使范围处于不一致的状态。例如,如果初始状态是(0, 5),同一时间内,线程 A 调用setLower(4) 并且线程 B 调用setUpper(3),显然这两个操作交叉存入的值是不符合条件的,那么两个线程都会通过用于保护不变式的检查,使得最后的范围值是(4, 3) —— 一个无效值。

 

这些条件表明,可以被写入 volatile 变量的这些有效值独立于任何程序的状态,包括变量的当前状态。

 

参考链接:http://www.importnew.com/18126.html

https://www.cnblogs.com/ouyxy/p/7242563.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值