Java语言中内存模型 JMM 提供了一个统一的指导准则

Happen-before关系,是Java内存模型中多线程操作的可见性机制

具体表现,不止是synchronized volatile lcok操作顺序

线程的执行操作,保证了happen-before后面的操作,保证了基本的程序执行顺讯

对于volatile比那辆,写的操作,保证happen-before于该变量的读取操作

对于一个锁的解锁,保证happen-before 于加锁操作

对象构建完成,保证happen-before 于 finalizer的开始动作

线程内部的操作完成,保证happen-beofre其他线程的 Thread.join的线程

对于JMM,有一个建议,就是要克制技术的诱惑,除了编译器和JVM工程师,不然不要一口扎入胡不进去,增加无为的难度,也没有实践的价值

那么我们主要说的是

需要明白JMM要解决什么问题?

JMM如何解决可见性问题,类似volatile

Java早期尝试提供内存模型,这是为了避免C++因为没有内存模型,导致的处理器上不同的问题

而且,早期并不能保证一些多线程程序的正确性,比如双检锁,就是典型的并发编程中的安全发布失败,而且很难做到一次编译,处处运行

所以Java需要一个完善的JMM,能够让多方清晰地达成共识,简单的判断多线程程序什么样的执行顺序是正确的

对于JMM,分为JVM开发者和Java应用开发者

JVM开发者 编译器 更加关注于内存屏障之类的技术

Java应用开发者,关注于volatile synchronize之类的语义,类似happen-before的规则

图片

JVM的内部运行数据区中运行如下,就是本地变量等数据从内存加载到缓存,寄存器,然后运行完成写入内存

图片

上面的架构带来的一个问题,就是修改完成如果没有即时同步到缓存中,可能导致其他内核上线程还是旧的状态,原则上就是一致性的问题,多线程共享引入了复杂的数据依赖性,这就是JMM要解决的问题

JMM内部利用内存屏障,禁止某些重排序的方式,提供内存可见性保证,实现了各种happen-before规则,保证了不同编译器拥有一致的行为

比如一个volatile变量,JMM的操作如下

对于一个volatile变量

变量的写操作之后,编译器插入一个写屏障

变量的读操作之前,插入一个读屏障

内存屏障在变量的读写之后,会保证其他的线程修改对当前线程可见,即线程的会强制写入刷出处理器缓存,保证其他线程能够拿到最新的值

从应用开发者的角度,JMM提供的诸如volatile就是可以进行线程之间守护上下文的作用,线程A对volatile的赋值,会导致线程B在获取的时候可见性,当然也带来了一些线程的性能开销

发表评论

邮箱地址不会被公开。 必填项已用*标注