• 01-并发编程bug源头:可见性、原子性和有序性


    一、可见性

      是指多线程在不同cpu缓存(多核)中对同一个变量进行修改,导致的不可见

    二、原子性

      指线程间切换导致的原子性问题

      一条编程语句执行往往包含多条CPU指令,操作系统做任务切换,可以发生在任意一条cpu指令执行完

      比如count+=1;这条语句包含3条cpu指令:

      1.把变量count从内存中加载到cpu寄存器;

      2.在cpu寄存器中执行+1操作

      3.把结果写入内存(也可能是因为缓存机制写入的是cpu缓存而不是内存)

    三、有序性

     因为编译器优化导致程序语句的执行顺序发生变化。

    经典案例就是单例模式中利用双重检查创建单例对象。

     1 public class Singleton{

    3 private static Singleton instance; 4 5 private static Singleton getInstance(){ 6 7   if(instance==null){ 8 9     sychronized(Singleton.class){ 10 11       if(instance==null){ 12 13         instance=new Singleton(); 14 15       } 16 17     } 18 19   } 20 21   return instance; 22 23 } 24 25 }

    问题出在new操作上,我们以为的操作是这样的:

      1.分配一块内存M;

      2.在内存M上初始化Singleton对象

      3.将地址M赋值给变量instance

    而实际上经过编译优化的执行操作是这样的:

      1.分配一块内存M;

      2.将地址M赋值给变量instance

      3.在内存M上初始化Singleton对象

    解决办法:把属性Singleton instance加修饰符volatile就完美了,对instance进行volatile语义声明,就可以禁止指令重排序。

    四、关于volatile资料参考:https://www.jianshu.com/p/ccfe24b63d87
    volatile 是一个类型修饰符。volatile 的作用是作为指令关键字,确保本条指令不会因编译器的优化而省略。
    volatile 的特性
    保证了不同线程对这个变量进行操作时的可见性,即一个线程修改了某个变量的值,这新值对其他线程来说是立即可见的。(实现可见性)
    禁止进行指令重排序。(实现有序性)
    volatile 只能保证对单次读/写的原子性。i++ 这种操作不能保证原子性。

    五、关于cpu缓存、线程工作内存:https://blog.csdn.net/u013851082/article/details/70314778/

  • 相关阅读:
    (转)Shell中read的用法详解
    How to install OpenResty
    MYSQL随机抽取查询 MySQL Order By Rand()效率问题
    NGINX、PHP-FPM开机自动启动
    Nginx和PHP-FPM的启动/重启脚本 [转发]
    绕过 <?PHP exit('Access Denied'); ?> 限制
    OpenResty(Nginx)+Lua+GraphicsMagick实现缩略图功能
    ImageMagick资料
    MySQL5.5 RPM安装的默认安装路径
    PHP编译支持mysqli
  • 原文地址:https://www.cnblogs.com/bbsh/p/11649454.html
Copyright © 2020-2023  润新知