1、由Volatile实现过程,看计算机多核CPU与内存的交互
相关解释:
a、Volatile修饰的变量,会生成Lock前缀的操作指令,Lock前缀指令会引起处理器缓存回写到内存。
b、当CPU 1修改volatile变量,系统内存中值和其他CPU中的缓存失效是即时性的。
c、红色箭头的嗅探操作:嗅探一个处理器来检测其他处理器打算写内存地址,而这个地址当前处于共享状态,那么正在嗅探的处理器将使它的缓存行无效,在下次访问相同内存地址时,强制执行缓存行填充。(类似一个Listener操作)
关键词:
a、内存屏障:上图中当CPU 1修改本地多级缓存并且要写回内存时,会禁止其他CPU操作内存中的值,这个行为被称为内存屏障。
b、MESI协议: 当一个CPU修改了本地中的多级缓存,会通知其他缓存了这个数据的CPU,其他CPU会把Cache中这份数据的Cache Line置为无效,要读取数据的话,直接去内存中获取,不会再从Cache中获取了。
2、Java内存模型(Java Memory Mode, JMM)
思考:
a、我们都知道,java之所以能在多种操作系统中运行,是因为java“自带了”自己的运行容器:JVM。
b、Java又是支持多线程的,多线程操作访问相同的变量,自然也会有类似上面“多核CPU访问操作同一内存地址且要保证缓存一致性的问题”,所以Java也实现了自己的内存模型。
线程1和线程2都有主内存中共享变量a的副本,初始时,这3个内存中a的值都为0。线程1中更新a的值为1之后同步到线程2主要涉及2个步骤:
(1)、线程1把线程工作内存中更新过的a的值刷新到主内存中。
(2)、线程2到主内存中读取线程1之前已更新过的a变量。
可以看的出来,JMM和计算机多核CPU在处理“高速缓存和内存”的交互上,是非常相似的。
3、JVM内存中的Java对象
思考:为什么Java对象模型没有看到对象方法?
//对象存储的定义
class oopDesc {
friend class VMStructs;
friend class JVMCIVMStructs;
private:
//重点 mark word 字段
volatile markWord _mark;
//重点 Class 字段
union _metadata {
// 对象方法就存在了这里,存放的是指针。为何只需要存放一个指针?因为同一个类的不同实例,包含的方法都是一样,为了节省空间,只需要保存相同的指针就可以了
Klass* _klass;
narrowKlass _compressed_klass;
} _metadata;
// There may be ordering constraints on the initialization of fields that
// make use of the C++ copy/assign incorrect.
NONCOPYABLE(oopDesc);
public:
// Must be trivial; see verifying static assert after the class.
oopDesc() = default;
}
4、Mark Word,Java对象的状态标识
由上图可以看出Java对象的五种状态:
5、总结与思考:
a、关于对偏向锁的理解
偏向锁只是逻辑上的锁,是一个概念。偏向锁干的事就是为了保证线程重入的情况下,可以不触发CAS或Mutex锁。由上面的图可以看出,偏向锁记录了“当前线程指针JavaThread”,之所要记录线程指针,是为了判断类似 if(threadId == currentThreadId), 那么跳过获取锁的过程。总结就是:偏向锁是为了线程重入。
b、为什么Mark Word中会用01 来表示无锁的状态 而不是用00表示无锁的状态?
待补充......
c、class oopDesc中,volatile markWord _mark,是否表示Mark Word是由Volatile实现的?
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。