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变量相关的指令不做重排序;
     
        以此来保证多线程的可见性。
  • 相关阅读:
    一起谈.NET技术,浅析ASP.NET清空缓存时遇到的问题 狼人:
    一起谈.NET技术,.NET平台上的ModelViewPresenter模式实践 狼人:
    一起谈.NET技术,.Net下的分布式缓存从Discuz!NT的缓存设计谈起 狼人:
    一起谈.NET技术,.NET缓存机制探讨与比对 狼人:
    一起谈.NET技术,.Net下的分布式缓存(2)实现分布式缓存同步的手段 狼人:
    一起谈.NET技术,.Net下的分布式缓存(3)如果我们没有缓存会怎么样 狼人:
    newlisp的lambda表达式
    SQL Server2008登录记录怎么删除?
    线段树端点更新 poj 2828 Buy Tickets
    111 History Grading
  • 原文地址:https://www.cnblogs.com/zhanvo/p/11845693.html
Copyright © 2011-2022 走看看