• 多线程003volatile的可见性和禁止指令重排序怎么实现的


    在代码种加入volatile关键字时,生成的汇编代码会出现一个locl前缀指令。

    local前缀指令实际上相当于一个内存屏障,它有3个功能:

    1.它确保指令重排序时不会把后面的指令排到内存屏障之前的位置,也不会把前面的指令排到内存屏障的后面。即在执行到内存屏障位置时,它前面的操作已全部完成。

    2.它会强制将对缓存的修改操作立即写入主存。

    3.如果是写操作,它会导致其他CPU中对应的缓存行无效。

    所以可见性和禁止指令重排序如下:

    可见性:

    volatile的功能就是被修饰的变量的值修改后,可以立即同步到主内存,被修饰的变量在每次用之前都从主内存刷新。本质也是通过内存屏障来实现可见性。

    写内存屏障可以促使处理器将当前store buffer(存储缓存)的值写回主存。

    读内存屏障可以促使处理invalidate queue(失效队列)。从而避免存储缓存和失效队列的非实时性带来的问题。

    禁止指令重排:

    volatile是通过内存屏障来禁止指令重排,JMM内存屏障策略:storestore、storeload、loadload、loadstore

    store为写操作,load为读操作。

    典型使用场景为单例模式的双重检查机制,代码如下:

     1 public class MultiThreadSingleton {
     2 
     3     private static volatile MultiThreadSingleton multiThreadsSingleton = null;
     4 
     5     private MultiThreadSingleton() {
     6         System.out.println("MultiThreadSingleton init");
     7     }
     8 
     9     public static MultiThreadSingleton getInstance() {
    10         if (multiThreadsSingleton == null) {
    11             synchronized (MultiThreadSingleton.class) {
    12                 if (multiThreadsSingleton == null) {
    13                     multiThreadsSingleton = new MultiThreadSingleton();
    14                 }
    15             }
    16         }
    17         return multiThreadsSingleton;
    18     }
    19 
    20     public static void main(String[] args) {
    21         // TODO Auto-generated method stub
    22         for (int i = 0; i < 10; i++) {
    23             new Thread(() -> {
    24                 MultiThreadSingleton.getInstance();
    25             }).start();
    26         }
    27 
    28     }
    29 }
  • 相关阅读:
    二叉树的下一个节点
    二叉树的对称
    CString,string和char*
    二叉平衡树
    二叉树的深度
    必应首页图片下载
    Git报错:fatal: remote origin already exists.
    sublime text3 自定义代码片段
    atom自定义C++代码片段
    vscode 自定义代码片段(snippets)
  • 原文地址:https://www.cnblogs.com/asenyang/p/15565403.html
Copyright © 2020-2023  润新知