并发编程之内存模型

Posted housh

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了并发编程之内存模型相关的知识,希望对你有一定的参考价值。

本章要点详细介绍以下几个问题:

1、为什么需要内存模型

2、什么是内存模型

3、内存模型解决什么问题

 

1、为什么需要内存模型

  说道内存模型不得不首先说下目前的计算机组成原理,目前主流的计算机都是冯诺依曼机。他的cpu缓存存原理如下图:

  当有了多级缓存后,CPU要读取一个数据时,首先从一级缓存中查找,如果没有找到再从二级缓存中查找,如果还是没有就从三级缓存,三级缓存没有就去主内存中查找。

  当多核多线程,同时访问一个共享变量的时候,就会在各自L1缓存里复制一份副本,多线程同时写的时候每个副本会出现数据不一致情况,回写到主存中可能会出现缓存不一致。

  这时就需要引入内存模型来避免这种问题。

  技术图片

2、什么是内存模型

  首先内存模型是一种规范,是解决由于多线程通过共享内存进行通信时,存在的本地内存数据不一致、编译器会对代码指令重排序、处理器会对代码乱序执行等带来的问题。

3、内存模型解决什么问题

  内存模型解决了并发编程场景中的原子性、可见性和有序性问题。

  1)如何解决原子性问题:

    在Java中,为了保证原子性,提供了两个高级的字节码指令monitorenter和monitorexit。在synchronized的实现原理文章中,介绍过,这两个字节码,在Java中对应的关键字就是synchronized。因此,在Java中可以使用synchronized来保证方法和代码块内的操作是原子性的。

  2)如何解决可见性问题:

    提到可见性,就要说下JMM的缓存一致性协议(MESI)即:modify,exclusive,share,Invalid。

      modify:数据被修改了,导致线程cache中和主存的数据不一致时,就是modify状态

      exclusive:独占状态,数据只存在于一个线程的cache中

      share:共享状态:数据存在于多个线程的cache中

      invalid:线程1修改了共享变量回写到主存中,就是导致线程2中cache中的变量是invalid状态,如果线程2需要使用该变量需要重新从主存中获取。

    volatitle由于实现了MESI协议,所以可以保证多线程操作共享变量的可见性。

    除了volatile,Java中的synchronizedfinal两个关键字也可以实现可见性,只不过是保证同一时刻只允许一条线程操作。

  3)如何解决有序性问题:

    jvm执行指令时,为提高执行速度会指令重排序,这样就导致执行结果可能会与预期不符,那如何解决呢?

      1)使用volatile解决:volatile关键字前后,由于会有读写内存屏障,保证指令不能重排序

      2)synchronized解决:synchronized保证同一时刻只允许一条线程执行

    

以上是关于并发编程之内存模型的主要内容,如果未能解决你的问题,请参考以下文章

并发编程系列之什么是Java内存模型?

并发编程(学习笔记-共享模型之内存)-part4

并发编程之内存模型

并发编程之内存模型

转:Java并发编程之十六:深入Java内存模型——happen-before规则及其对DCL的分析(含代码)

JUC并发编程 共享模型之内存 -- Java 内存模型 & 原子性 & 可见性(可见性问题及解决 & 可见性 VS 原子性 & volatile(易变关键字))(代码