码迷,mamicode.com
首页 > 编程语言 > 详细

Java内存模型

时间:2017-02-27 23:24:06      阅读:348      评论:0      收藏:0      [点我收藏+]

标签:模型   before   执行   特定   断线   数组   变量   改变   int   

多线程如何通信,同步?

1)通信: 共享内存/消息队列

2)同步: 访问时加锁/消息队列

JMM采用共享内存以及访问时加锁。JMM决定一个线程对变量的写入何时对另一个线程可见。

Java中,静态变量/实例变量/数组元素都分配在堆中,而局部变量/方法参数/异常变量分配在栈中。线程共享堆,但是独有栈。所以栈不存在共享可见性问题。

每个线程有自己的工作内存,可能是缓存/写缓冲区/寄存器等。线程间通信时,线程A先写到工作内存,再刷新到主内存;然后线程B从主内存读取最新数据到工作内存并创建副本。由于存在重排序,所以结果可能有所不同。

重排序:

1)编译器优化的重排序: 改变代码执行顺序

2)处理器优化的重排序:指令级并行技术(ILP),能并发执行多条指令,改变执行顺序

3)内存重排序: 由于用缓存和读写缓冲区,使得load和store可能乱序执行

JMM的编译器会禁止特定类型的编译器重排序,JMM的处理器通过插入内存屏障(Load/Load, Load/Store, Store/Load, Store/Store)禁止特定类型的处理器重排序。

如果一个操作对另一个操作存在可见性,必须满足happens-before规则。如果两个操作缺乏happens-before关系,JVM可以任意重排序。

happens-before规则:

1)程序规则:之前的代码先于后面的代码执行

2)锁规则: unlock先于lock执行

3)volatile规则: 写入先于读取执行

4)线程启动规则:Thread.start()优于所有后续动作执行

5)线程终止规则: 线程中所有动作必须先于其它线程检测到该线程结束执行

6)线程中断规则: 当一个线程在另一个线程上调用interrupt,必须在被中断线程检测到interrupt之前执行

7)终结器规则: 对象的构造函数必须在启动该对象的终结器之前执行完成。

8)传递规则: A happens-before B, B happens-before C -> A happens-before C

 

volatile, synchronized, Lock, final能保证内存可见性。volatile变量每次从主内存load数据,synchronized和Lock在开始的时候将内存数据copy到工作内存,结束的时候将工作内存的数据refresh到主内存。final变量一旦初始化完,对其他线程立即可见。

volatile, synchronized能保证有序性。volatile通过插入内存屏障禁止重排序,synchronized通过每次只允许一个线程对一个变量加锁。

Java内存模型

标签:模型   before   执行   特定   断线   数组   变量   改变   int   

原文地址:http://www.cnblogs.com/lruihan/p/6476646.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!