提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档
目录
一、Java内存模型出现的背景
二、什么是Java内存模型
三、Java内存模型的底层实现
总结
提示:以下是本篇文章正文内容,下面案例可供参考
一、Java内存模型出现的背景
操作系统的优化,带来的缓存可见性问题和指令重排导致的原子性问题。
这些都是操作系统的供应商为了提高系统性能,所做出的升级优化。
但是这些升级优化,恰恰在多CPU场景下,引发其他的问题。
人们在着手解决这些问题的时候,发现,不能盲目的全部禁用这些优化,因为那样的话,我们的程序就又回到了单CPU的时代,再加上锁的竞争,可能性能会更加的慢。
既然不能全部禁用,那么就灵活一些,将禁用的主动权交给编写程序的人,我们的主角即将登场——Java内存模型
二、什么是Java内存模型
Java内存模型,规范了JVM如何提供按需禁用缓存和编译优化的方法
通俗的讲,就是约定了按需禁用缓存和编译优化的关键字、方法等等。
来讲两个例子,大家就知道说的是什么了,例如:修饰变量的关键字volatile、final、synchronized关键字。也就是说这些个Java的关键字,是为了禁用缓存和编译优化而生。
三、Java内存模型的底层实现
上边讲的是Java内存模型的体现形式,通过关键字,让开发人员自己控制。
那么接下来讲一讲,这些关键字的底层实现——内存屏障(memory barrier)
我们对如下语句进行反编译
synchronized (this) {
System.out.println("Method 1 start");
}
反编译结果:
指令解释——monitorenter:
Each object is associated with a monitor. A monitor is locked if and only if it has an owner. The
thread that executes monitorenter attempts to gain ownership of the monitor associated with
objectref, as follows:
• If the entry count of the monitor associated with objectref is zero, the thread enters the monitor
and sets its entry count to one. The thread is then the owner of the monitor.
• If the thread already owns the monitor associated with objectref, it reenters the monitor,
incrementing its entry count.
• If another thread already owns the monitor associated with objectref, the thread blocks until the
monitor's entry count is zero, then tries again to gain ownership
翻译成中文
每个对象有一个监视器锁(monitor)。当monitor被占用时就会处于锁定状态,线程执行monitorenter指令时尝试获取monitor的所有权,过程如下:
1、如果monitor的进入数为0,则该线程进入monitor,然后将进入数设置为1,该线程即为monitor的所有者。
2、如果线程已经占有该monitor,只是重新进入,则进入monitor的进入数加1.
3.如果其他线程已经占用了monitor,则该线程进入阻塞状态,直到monitor的进入数为0,再重新尝试获取monitor的所有权
指令解释——monitorexit:
The thread that executes monitorexit must be the owner of the monitor associated with the instance
referenced by objectref.
The thread decrements the entry count of the monitor associated with objectref. If as a result the
value of the entry count is zero, the thread exits the monitor and is no longer its owner. Other
threads that are blocking to enter the monitor are allowed to attempt to do so.
翻译成中文
执行monitorexit的线程必须是objectref所对应的monitor的所有者。
指令执行时,monitor的进入数减1,如果减1后进入数为0,那线程退出monitor,不再是这个monitor的所有者。其他被这个
monitor阻塞的线程可以尝试去获取这个 monitor 的所有权
从上可以看出,底层用了监视器锁来限制指令的重排。
总结
新事物的出现并非偶然,带着解决问题的思路去思考。