volatile 关键字 内存可见性

一 .解释

1.内存可见性(Memory Visibility)是指当某个线程正在使用对象状态 而另一个线程在同时修改该状态,需要确保当一个线程修改了对象 状态后,其他线程能够看到发生的状态变化。

2. 可见性错误是指当读操作与写操作在不同的线程中执行时,我们无 法确保执行读操作的线程能适时地看到其他线程写入的值,有时甚 至是根本不可能的事情。

3.我们可以通过同步来保证对象被安全地发布。除此之外我们也可以 使用一种更加轻量级的 volatile 变量。

4.Java 提供了一种稍弱的同步机制,即 volatile 变 量,用来确保将变量的更新操作通知到其他线程。 可以将 volatile 看做一个轻量级的锁,但是又与 锁有些不同:

    4.1对于多线程,不是一种互斥关系 ;

    4.2 不能保证变量状态的“原子性操作”;如(i++ 的原子性问题:i++ 的操作实际上分为三个步骤“读-改-写”)

二. 测试Demo如下:

/*
 * 一、volatile 关键字:当多个线程进行操作共享数据时,可以保证内存中的数据可见。
 *                       相较于 synchronized 是一种较为轻量级的同步策略。
 * 
 * 注意:
 * 1. volatile 不具备“互斥性”
 * 2. volatile 不能保证变量的“原子性”
 */
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 {

    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;
    }
}

三.如何解决(针对volatile)

共享数据可以用原子变量,(原子变量:在 java.util.concurrent.atomic 包下提供了一些原子变量)

特点:1.原子变量底层都被 volatile 保证内存可见性
         2. 利用CAS(Compare-And-Swap) 算法又保证数据变量的原子性
             其中CAS 算法是硬件对于并发操作的支持针对多处理器 操作而设计的处理器中的一种特殊指令,用于管理对共享数据 的 并 发访问。
             CAS 包含了三个操作数:
             ①内存值  V(刚开始线程读取的值)
             ②预估值  A  (将要修改时再次读取的值)
             ③更新值  B   (将要改成的值)
             当且仅当 V == A 时, V = B; 否则,不会执行任何操作。

   //  private volatile int serialNumber = 0;      serialNumber ++;
    private AtomicInteger serialNumber = new AtomicInteger(0);  serialNumber.getAndIncrement();//自增

猜你喜欢

转载自blog.csdn.net/weixin_39494923/article/details/81360228