Java提高——JUC线程volatile关键和内存可见性

内存可见性

  • 内存可见性:是指当某个线程正在使用对象状态而另一个线程在同时修改该状态,需要确保当一个线程修改了对象状态之后,其他线程能够看到发生的状态变化。
  • 可见性错误:当读操作与写操作在不同的线程中执行时,我们无法确保执行读操作的线程能实时的看到其他线程写入的值,有时甚至是不可能的事情。
  • 我们可以通过对象同步来保证对象被安全的发布。除此之外我们也可以使用一种更加轻量级的volatile变量。
class Condition implements Runnable{
    private boolean flag = false;

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

    public boolean isFlag(){
        return flag;
    }

    @Override
    public void run() {
        try {
            Thread.sleep(2000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        flag = true;
        System.out.println("flag 已经变为 "+isFlag());
    }
}
public class TestVolatile {
    public static void main(String[] args) {
        Condition con = new Condition();
        new Thread(con).start();
        while (true){
            if (con.isFlag()){
                System.out.println("=====阿西吧=====");
                break;
            }
        }
    }
}

《Java提高——JUC线程volatile关键和内存可见性》

上面的main线程和Condition线程并没有共享flag变量。

当我们运行程序时,JVM会为每个线程分配一个独立的缓存用于提高效率

《Java提高——JUC线程volatile关键和内存可见性》

解决方案一:使用同步块(可以每次都刷新缓存重复的到主存中读数据)

public class TestVolatile {
    public static void main(String[] args) {
        Condition con = new Condition();
        new Thread(con).start();
        while (true){
            synchronized (TestVolatile.class) {
                if (con.isFlag()) {
                    System.out.println("=====阿西吧=====");
                    break;
                }
            }
        }
    }
}

《Java提高——JUC线程volatile关键和内存可见性》

但是锁会使效率低下。

解决方案二:volatile关键字(效率也会降低但是比锁的效率高)

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

  • 对于多线程,不是一种互斥关系
  • 不能保证变量状态的“原子性操作”
/**  * @author chenpeng  * @date 2018/7/10 15:23  *  * volatile关键字:保证多个线程访问共享数据时,彼此的数据是可见的  * (原理就是实时把缓存中的数据刷新到主存中)  * 相较于synchronized是一种轻量级的同步策略  *  * 注意:  * 1、volatile不具备“互斥性”  * 2、volatile不能保证变量的“原子性”  */ class Condition implements Runnable{
    private volatile boolean flag = false;

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

    public boolean isFlag(){
        return flag;
    }

    @Override
    public void run() {
        try {
            Thread.sleep(2000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        flag = true;
        System.out.println("flag 已经变为 "+isFlag());
    }
}
public class TestVolatile {
    public static void main(String[] args) {
        Condition con = new Condition();
        new Thread(con).start();
        while (true){
            if (con.isFlag()) {
                System.out.println("=====阿西吧=====");
                break;
            }
        }
    }
}

    原文作者:JUC
    原文地址: https://blog.csdn.net/qq_30604989/article/details/80986798
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞