java多线程编程(五)

版权声明:本文为RoundYuan原创文章,转载请注明出处! https://blog.csdn.net/ProgramMonika/article/details/85924384

java多线程编程(五)

     java内存模型分类

使用写缓冲区临时保存向内存中写入数据。

Why?

提升效率:

1)写缓冲区可以保证指令流水线持续运行,它可以避免由于处理器停顿下来等待向内存写入数据而产生的延迟

2)通过以批处理的方式刷新写缓冲区,以及合并写缓冲区中对同一内存地址的多次写,减少对内存总线的占用。

缺点:

每个处理器上的写缓冲区,仅仅对它所在的处理器可见。这个特性会对内存操作的执行顺序产生重要的影响:处理器对内存的读/写操作的执行顺序,不一定与内存实际发生的读/写操作顺序一致

eg:

处理器/示例项 ProcessorA ProcessorB
代码
a=1; //A1x=b;//A2

b=2;//B1y=a;//B2
运行结果
初始状态:a=b=0;处理允许执行后得到的结果:x=y=0

具体原因如下:

处理器A和处理器B可以同时把共享变量写入到自己的写缓存区(A1,B1),然后从内存中
读取另一个共享变量(A2、B2),最后才把自己写缓存区中保存的脏数据刷新到内存中(A3、B3)当以这种时序执行时,程序就可以得到x=y=0的结果。

从内存操作实际发生的顺序来看,直到处理器A执行A3来刷新自己的写缓存区,写操作
A1才算真正执行了。虽然处理器A执行内存操作的顺序为:A1→A2,但内存操作实际发生的顺
序却是A2→A1。此时,处理器A的内存操作顺序被重排序了(处理器B的情况和处理器A一样,
这里就不赘述了)。

这里的关键是,由于写缓冲区仅对自己的处理器可见,它会导致处理器执行内存操作的
顺序可能会与内存实际的操作执行顺序不一致。由于现代的处理器都会使用写缓冲区,因此现代的处理器都会允许对写-读操作进行重排序

happens-before简介

在JMM中,如果一
个操作执行的结果需要对另一个操作可见,那么这两个操作之间必须要存在happens-before关
系。这里提到的两个操作既可以是在一个线程之内,也可以是在不同线程之间。

与程序员密切相关的happens-before规则如下:

  • 程序顺序规则:一个线程中的每个操作,happens-before于该线程中的任意后续操作。

  • 监视器锁规则:对一个锁的解锁,happens-before于随后对这个锁的加锁。

  • volatile变量规则:对一个volatile域的写,happens-before于任意后续对这个volatile域的
    读。

  • 传递性:如果A happens-before B,且B happens-before C,那么A happens-before C。

happens-before与JMM关系如下:
在这里插入图片描述

猜你喜欢

转载自blog.csdn.net/ProgramMonika/article/details/85924384