• 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也能解决一定的有序性.

  • 相关阅读:
    xtrabackup增量备份mysql +MHA
    mysql备份恢复中的常见错误
    MySQL 面试题目
    Amoeba for MySQL 中间件
    [MySQLCPU]线上飙升800%,load达到12的解决过程
    pt-kill--- MySQL数据库CPU飙升紧急处理方法
    MySQL 5.7并行复制时代
    淘宝内部分享:怎么跳出MySQL的10个大坑
    Percona XtraBackup User Manual 阅读笔记
    淘宝内部分享:MySQL & MariaDB性能优化
  • 原文地址:https://www.cnblogs.com/trekxu/p/9843217.html
Copyright © 2020-2023  润新知