Java内存模型

一、为什么会出现内存模型

       计算机的处理器速度快,存储设备速度慢,处理器和存储设备的速度之间有几个数量级的差距。为了更充分的利用计算机处理器的效能,现代计算机系统中加入了一层读写速度尽可能接近处理器速度的高速缓存来作为处理器和内存之间的缓冲:将运算需要的数据复制到缓存中使得运算能快速进行,当运算结束后再从缓冲同步到内存中,这样处理器就无需等待缓慢的内存读写了。
       基于高速缓存的存储交互很好的解决了处理器和存储设备的速度矛盾,但却引入了一个新的问题:缓存一致性。每个处理器都有自己的高速缓存,而它们都共用同一内存。当多个处理器都涉及同一块内存数据时,将可能导致各自的缓存数据不一致。为了解决一致性问题,在读写时需要根据协议来进行操作。内存模型可以理解为在特定的操作协议下,对特定的内存或高速缓存进行读写访问的过程抽象。不同架构的物理机可以拥有不一样的内存模型,而Java虚拟机也有自己的内存模型。Java内存模型可以屏蔽掉各种硬件和操作系统的内存访问差异,以实现让Java程序在不同平台下都能达到一致的内存访问效果

二、Java内存模型

       Java内存模型的主要目标是定义程序中各个变量的访问规则,即在虚拟机中将变量存储到内存和从内存中取出变量这样的底层细节。此处的变量是指实例字段、静态字段和构成数组对象的元素,但不包括局部变量与方法参数,因为后者是线程私有的,不会被共享。
       Java内存模型规定了所有的变量都存储在主内存中,每条线程还有自己的工作内存,线程的工作内存保存了线程需要使用的变量的主内存副本拷贝,线程对变量的所有操作都必须在工作内存中进行,而不能直接读写主内存中的变量。不同的线程之间也无法访问对方工作内存中的变量,线程间变量值的传递均需要通过主内存来进行。
Java Memory Model

三、volatile关键字

1.可见性: 对于一个volatile变量,当一条线程修改了这个变量的值,新值对于其他线程来说是立即得知的。
2.禁止指令重排序: 在JVM中通过内存屏障实现,在重排序时不能把后面的指令重排到内存屏障之前的位置。

四、原子性、可见性与有序性

1.原子性
        由Java内存模型来直接保证的原子性变量操作包括read、load、assign、use、store和write。基本类型数据的访问读写是需要具备原子性的。如果需要一个更大的原子性保证,可以使用字节码指令monitorenter和monitorexit来隐式使用lock和unlock操作,这两个字节码反映到Java代码中就是同步块----synchronized关键字。
2.有序性
       Java内存模型通过在变量修改后将新值同步回主内存,在变量读取前从主内存刷新变量值这种依赖主内存作为传递媒介的方式来实现可见性的。volatile的特殊规则保证了新值能立即同步到主内存,以及每次使用前立即从主内存刷新。
       除volatile之外,synchronized和final这两个关键字也能实现可见性。synchronized的可见性是由“对一个变量执行unlock操作之前,必须先把此变量同步回主内存中(执行store、write操作)”这条规则获得的。而final关键字的可见性是指:被final修饰的字段在构造器中一旦初始化完成,并且构造器没有把"this"的引用传递出去,那在其他线程中就能看见final字段的值。
3.有序性
        Java语言提供了volatile和synchronized两个关键字来保证线程之间操作的有序性。volatile关键字本身就包含了禁止指令重排序的语义,而synchronized则是由“一个变量在同一时刻只允许一条线程对其进行lock操作”这条规则获得的,这条规则决定了持有同一个锁的两个同步块只能串行地进入。

五、线程的实现

1.使用内核线程实现
       内核线程(Kernel Level Thread,KLT)就是直接由操作系统内核支持的线程,这种线程由内核完成线程切换,内核通过操纵调度器对线程进行调度,并负责将线程的任务映射到各个处理器上。程序一般不会直接去使用内核线程,而是去使用内核线程的一种高级接口----轻量级进程(Light Weight Process,LWP),轻量级进程就是我们通常意义上所讲的线程。轻量级进程和内核线程之间是1:1的关系。(一对一的线程模型)
2.使用用户线程实现
       由于没有系统内核的支援,线程的创建、切换和调度都要自己实现,比较复杂,一般不用。
3.使用用户线程加轻量级进程混合实现
4.Java线程的实现
       Java线程是基于操作系统原生线程模型来实现的。操作系统支持什么样的线程模型,决定了Java虚拟机的线程是怎样映射的,这点在不同的平台上没有办法达成一致。线程模型只对线程的并发规模和操作成本产生影响,对Java程序的编码和运行过程来说,这些差异都是透明的。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值