0
点赞
收藏
分享

微信扫一扫

juc原理-1

12a597c01003 2022-03-12 阅读 112
jucjava

JMM(Java Memory Model)
每个Java线程都有⾃⼰的⼯作内存。操作数据,⾸先从主内存中读,得到⼀份拷⻉,操作完毕后再写回到主内存。
 

由于JVM运⾏程序的实体是线程,⽽每个线程创建时JVM都会为其创建⼀个⼯作内存⼯作内存是每个线程的私有数据区域,⽽Java内存模型中规定所有变量都存储在
主内存,主内存是共享内存区域,所有线程都可以访问,但线程对变量的操作(读取赋值等)必
须在⼯作内存中进⾏,⾸先要将变量从主内存拷⻉到⾃⼰的⼯作内存空间,然后对变量进⾏操
作,操作完成后再将变量写回主内存,不能直接操作主内存中的变量,各个线程中的⼯作内存中
存储着主内存中的变量副本拷⻉,因此不同的线程间⽆法访问对⽅的⼯作内存,线程间的通信
必须通过主内存来完成,这样就会导致可⻅性、 原⼦性和有序性问题
 

可⻅性:就是某个线程对主内存内容的更改,应该⽴刻通知到其它线程。
原⼦性:是指⼀个操作是不可分割的,不能执⾏到⼀半,就不执⾏了,i++,看上去是一条指令但是翻译成汇编指令后就变成了3条指令,volatile是不能保证原子性的
有序性:就是指令是有序的,不会被重排。cpu由于每秒可以执行10亿条指令,为了提高效率,cpu有可能会将两条毫无关系的指令(也就是说两条指令交换后不会影响到结果)进行排序
 

volatile的三大特性:

volatile可以保证可⻅性,及时通知其它线程主物理内存的值已被修改,某个线程对变量的修改,会⽴刻反映到主内存上

原⼦性指的是什么意思?
   不和分割,完整性,也即某个线程正则做某个具体业务时,中间不可以被被分割或者加上其他代码。,要么同时成功,要么同时失败

i++翻译成汇编指令:

2: getfield
5: iconst_1
6: iadd
7: putfield
#2 // Field number:I //读
//++常量1
//加操作
#2 // Field number:I //写操作

所以加上volatile也不能保证原子性,会导致多个线程操作i++达不到预想的结果,比如第一个线程还没有执行玩iadd,第二个线程进行读取,此时读取到的还是0,并不是第一个线程累加后的结果,所以多次累加后会导致结果变少,最主要的原因还是因为这个i++操作不是原子性的,如果要解决此类问题,用AtomicInteger可以解决问题,底层是通过cas来解决的。

volatile为什么能禁止指令重排?

CPU的jsr内存屏障(Memory Barrier)指令来实现的,包括ss,sl,ls,ll它有两个作⽤
⼀个是保证特定操作的顺序性
⼆是保证变量的可⻅性

也就是说:对volatile修饰的变量进行写操作,会在写操作后加上一个store指令凭证禁止器发生排序

dcl:double check lock修饰的变量一定要加上volatie

原理在之前jvm篇章已经详细分析过
 

举报

相关推荐

JUC 全套(1)

1 JUC概述

JUC之CAS原理

JUC原理之锁机制原理二

1.JUC并发编程

【JUC】Synchronized及JVM底层原理

0 条评论