美文网首页
BiBi - 并发编程 -5- Java内存模型

BiBi - 并发编程 -5- Java内存模型

作者: 奋飞的蜗牛ing | 来源:发表于2019-12-10 00:41 被阅读0次

From:Java并发编程的艺术

线程通信的两种机制:共享内存【隐式】和消息传递【显示】,Java的并发采用共享内存模型,线程A向线程B发送消息,这个通信过程必须经过主存。

指令重排序

编译器和处理器为了优化程序性能而对指令序列进行重新排序,但不会对存在数据依赖关系的操作做重排序。
1)编译器重排序
2)处理器重排序
包括:指令级并行的重排序【将多条指令重叠执行】和内存级重排序。
对于处理器重排序,在Java编译器生成指令序列时,通过插入特定类型的内存屏障【Memory Barriers / Memory Fence】指令来禁止重排序,从而保证内存的可见性。现代的处理器都采用写缓冲区向内存写入数据。

StoreLoad Barriers

StoreLoad Barriers屏障是一个【全能型】屏障,并且大部分处理器都支持,它会把写缓冲区中的数据全部刷新到内存中。开销很高。

happens-before

使用happens-before来阐述操作之间的内存可见性。
happens-before规则:
1)一个锁的解锁,先于随后对这个锁的加锁
2)volatile变量的写,先于任意后续对这个变量的的读【volatile的本质】
3)传递性:A先于B,B先于C,则A先于C

happens-before提示:
具有happens-before关系,并不意味着前一个操作必须要在后一个操作之前执行,仅仅要求前一个操作执行的结果对后一个操作可见,并且前一个操作按顺序排在第二个操作之前

如果A线程的写操作a与B线程的读操作b之间存在happens-before关系,尽管a操作和b操作在不同的线程中执行,但JMM保证a操作对b操作可见。

控制依赖重排序
if ( flag ) {  // 1
  int i = age + 10;  // 2
}

操作1和操作2存在控制依赖关系,他们重排序后,处理器可以提前读取并计算age + 10,然后把计算结果临时保存到一个重排序缓冲的硬件缓存中。当操作1的条件判断为真时,再把计算结果写入到变量i中。

顺序一致性

顺序一致性模型简介:
1)顺序一致性模型保证单线程内的操作会按程序的顺序执行,而JMM不保证单线程内的操作会按照程序的顺序执行【会重排序】。
2)顺序一致性模型保证所有线程只能看到一致的操作执行顺序,而JMM不保证。
3)JMM不保证对64位的long型和double型变量的写操作具有原子性【JDK1.5之后读具有原子性】,而顺序一致性模型保证对所有的内存读/写操作都具有原子性。

第3)点与处理器的总线机制有关。总线同步,在一个处理器执行总线事物期间,总线会禁止其他的处理器和I/O设备的读写操作。即总线工作机制:把所有处理器对内存的访问以串行化的方式来执行,在任意时间点,最多只能有一个处理器可以访问内存。确保单个总线事物之中的读写操作具有原子性。
在32位处理器上,JVM可能把一个64位long/double型变量的写操作拆分成两个32位的写操作来执行,这两个32位的写操作可能会被分配到不同的总线事物中执行,因此不具有原子性。【volatile类型的long/double读写都具有原子性】

在单线程中重排序不会改变执行结果,但在多线程中会影响执行结果。
临界区【锁保护区】内的代码可以重排序。

相关文章

网友评论

      本文标题:BiBi - 并发编程 -5- Java内存模型

      本文链接:https://www.haomeiwen.com/subject/pdzhkqtx.html