JMM Java Memory Model
2021.3.19号,花了一整个晚上的时间,从清醒到懵逼再到清醒的过程,这里简单记录一下,以免后面又忘记什么是JMM
JMM java memory model,他其实是用来解决当在多线程环境下,线程之间如何合作才能保证程序的结果是确定的。
1、java是内存共享来进行隐式的消息通信。
2、JMM规定了每个线程都有自动的工作内存,他们只能在自己的工作内存中对变量进行操作,而不能直接在共享的主内存中
3、那么在多个线程一起工作的时候,就会出现由于不可见行、指令重排、一组操作不是原子性的而引发程序执行结果的不确定。
4、所以JMM规定了可见性、有序性、原子性等规范来解决了上述问题
5、JMM规范的具体体现就是volatile 、 synchronized 、 lock、final 、 concurrent包等
volatile的实现原理:
volatile 保证可见性、有序性(禁止指令重排),是通过内存屏障来实现的
JMM定义了四种内存屏障:
loadloadbarrrier
: 这个屏障之前的装载,必须先于这个屏障之后的装载storestorebarrier
: 这个屏障之前的存储,必须先于这个屏障之后的存储loadstorebarrier
: 这个屏障之前的装载,必须先于这个屏障之后的存储storeloadbarrier
: 这个屏障之前的存储,必须先于这个屏障之后的装载
其中第四个内存屏障是万能的,他包含了上面三个屏障的所有功能。
那么把加了volatile关键字的变量放在两个内存屏障之间,就能够实现每当一个线程要对volatile变量,必须重新从主存中读取;每当操作完volatile对象,必须立刻将volatile变量刷新到主存中。从而保证了可见性和有序性(禁止指令重排)。
synchronized 的实现原理
1、每一个对象都有一个监视器monitor
2、synchronized 其实对应两条java字节码指令:monitorenter monitorexit
3、monitor的底层其实和操作系统的mutex lock(互斥锁)有关
4、互斥锁的开销很大,因为要完成线程之间的切换,需要从用户态转向内核态,很花费时间
5、所以经常使用synchronized关键字,会导致程序运行效率地下。
所以在jdk1.6之后,引用了偏向锁,轻量级锁的概念,从而使得在竞争不激烈的时候,不需要直接使用互斥锁这种重型锁,提高程序运行效率。
相关参数:
- 默认
-XX:+UseBiasedLocking=true
-XX:-UseBiasedLocking=false
关闭偏向锁- 应用程序启动几秒钟之后才激活
- -XX:BiasedLockingStartupDelay = 0关闭延迟