zoukankan      html  css  js  c++  java
  • 多线程学习之多线程的可见性

    多线程的可见性

      一、深入探究多线程的不确定性因素

    1 1、cpu高速缓存导致的极短时间内获取不到想要数据
    2 2、cpu指令重排导致之后的自行优化导致数据混乱;当然,这种情况值存在于多线程的基础上,单个线程是不会出现这种问题的。
    3 3、JIT会把多次方法区中多调用或者多次循环的数据进行换存,然后自行优化;这里缓存也会导致后来改变的数据无法被正常的获取。

      首先来说cpu的高速缓存,它是介于我们物理内存与程序之间。

      CPU高速缓存(英语:CPU Cache,在本文中简称缓存)是用于减少处理器访问内存所需平均时间的部件。在金字塔式存储体系中它位于自顶向下的第二层,仅次于CPU寄存器。

      其容量远小于内存,但速度却可以接近处理器的频率。

      当处理器发出内存访问请求时,会先查看缓存内是否有请求数据。如果存在(命中),则不经访问内存直接返回该数据;如果不存在(失效),则要先把内存中的相应数据载入缓存,再将其返回处理器。
     
      缓存之所以有效,主要是因为程序运行时对内存的访问呈现局部性(Locality)特征。这种局部性既包括空间局部性(Spatial Locality),也包括时间局部性(Temporal Locality)。
     
      有效利用这种局部性,缓存可以达到极高的命中率。
     
      在处理器看来,缓存是一个透明部件。因此,程序员通常无法直接干预对缓存的操作。但是,确实可以根据缓存的特点对程序代码实施特定优化,从而更好地利用缓存。
      
      这里说吧内存中的相应数据载入缓存,再将其返回处理器。在多线程的场景下,就会导致在极短的时间内导致数据获取不到。
     

      CPU指令重排:这种情况在单个线程下怎么重排都无所谓,不会出现值混乱,但是在多线程的环境下就可能出现值混乱。

     1 //就是说Java 编译器可能重新排列源代码执行的顺序来优化编译的表现,比如
     2 
     3 int a = 0, 
     4 int b = a + 1;
     5 int c = 2;
     6 
     7 //在编译成bytecode 以后,执行的顺序可能是
     8 int c = 2;
     9 int b = a + 1;
    10 int a = 0;

      JIT执行模型:

     

       二、JMM内存模型

        Java内存模型中规定:
        > 对某个 volatile 字段的写操作 happens-before 每个后续对该 volatile 字段的读操作。
        > 对 volatile 变量 v 的写入,与所有其他线程后续对 v 的读同步;
        
        Volatile如何实现它的语义:
        > 禁止缓存;
        volatile变量的访问控制符会加个ACC_VOLATILE
        https://docs.oracle.com/javase/specs/jvms/se8/html/jvms-4.html#jvms-4.5
        > 对volatile变量相关的指令不做重排序;
     
        以此来保证多线程的可见性。
  • 相关阅读:
    Sphere AABB Collision Detaction
    左右手坐标系的差别
    php 利用 soap调用.Net的WebService asmx文件
    NewLife.XCode 上手指南(五) 复杂查询
    NewLife.Xcode 上手指南(三) 扩展属性的使用
    JS获取URL参数
    [转]模态窗口使用总结
    Jquerysimplemodal的使用,弹出窗口,弹出页面
    NewLife.XCode 上手指南(四) 级联操作
    NewLife.XCode 上手指南
  • 原文地址:https://www.cnblogs.com/zhanvo/p/11845693.html
Copyright © 2011-2022 走看看