• 033 内存可见性和volatile关键词


    一 . JVM内存结构

      

    在上图之中,我们可以注意到JVM为了加快运行,使用了缓存机制,但是在使用了缓存机制之后,就会出现缓存的不一致性的问题.

    下面演示一个代码:

    public class VolatileTest {
    
        private Boolean flag = true;
    
        public static void main(String[] args) {
            VolatileTest demo = new VolatileTest();
    
            new Thread(() -> {
                for (;;) {
                    if (!demo.flag) {
                        System.out.println("end..");
                        return;
                    }
                }
            }).start();
    
            new Thread(() -> {
    
                try {
                    TimeUnit.SECONDS.sleep(3);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                demo.flag = false;
            }).start();
    
        }
    }

    上面的代码之中,我们期望在运行之后,我们设置的符号标记被修改掉,通过这样的方式,我们就能完成对第一个线程的停止.

    但是结果出乎我们的意料,第一个线程永远不会终结.


    二 .可见性

    造成层上面的问题的根源就是JVM的缓存机制导致的,第一个线程使用的是一个线程栈之中的副本,而这个副本永远都是true,因此我们上面的方式时永远不能停止线程的.

    可见性问题:
      在多线程并发的情况下,由于JVM的缓存机制造成缓存之间的不同步,(一个线程对一个变量进行了修改,但是另外的线程无法及时的知晓),这就是可见性问题.


    三 . 可见性问题的解决

      既然可见性的问题就是缓存不一致性引发出来的,因此我们只需要一个缓存同步的方法就能解决这个问题.

    在java之中,出现了volatile关键词,这个关键词帮助实现了对被volatile关键词修饰的变量一旦进行了修改,那么其他的线程一定会得到通知,从主存之中获取新的数据.

    通过这种方式,就解决了可见性问题.


    四 .轻量级同步方式

      通过上面的介绍,我们可以看出volatile是一个轻量级的同步工具,帮助我们解决了线程安全性问题.

      也就是说,可见性问题也是一种引起线程安全性问题的原因.

    在这里我们可以看到,解决线程安全性问题的方式:

    [1]原子性:

    [2]可见性:

    [3]有序性: 使用volatile也能解决一定的有序性.

  • 相关阅读:
    HDU 1257 最少拦截系统(最长递减子序列的条数)
    POJ 2063 Investment 滚动数组+完全背包
    POJ 2392 Space Elevator 贪心+dp
    CodeForces 154A Hometask dp
    CodeForces 57C Array 组合计数+逆元
    hdu 4398 Template Library Management(贪心+stl)
    优先队列详解(转载)
    hdu 4393 Throw nails(优先队列)
    hdu 4022 Bombing(map,multiset)
    hdu 1027 Ignatius and the Princess II(产生第m大的排列,next_permutation函数)
  • 原文地址:https://www.cnblogs.com/trekxu/p/9843217.html
Copyright © 2020-2023  润新知