ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

JUCJUC

2021-11-20 21:02:02  阅读:172  来源: 互联网

标签:变量 拿到 线程 内存 JUCJUC 操作 偏移


1.volatile

//轻量级的JAVA同步机制
特点1:保证内存可见性
对于普通的变量,线程A将其修改为某个值发生在线程A的本地内存中,此时还未同步到主内存中去;而线程B已经缓存了该变量的旧值,所以就导致了共享变量值得不一致。解决这种共享变量在多线程模型中的不可见性问题,比较粗暴的方式是加锁,但是太重量级,所以用volatile比较合理。
方式:(1)他会强制将对共享变量的修改操作立即写入主内存。
(2)如果是写操作,他会导致其他线程中的对应的缓存无效,所以其他线程用到该变量时,必须从主内存重新获取。
JAVA内存模型:由于JVM运行程序的实体是线程,而每个线程创建时JVM都会为其创建一个工作内存(有些地方成为栈空间),工作内存是每个线程的私有数据区域,而Java内存模型中规定所有变量都存储在主内存,主内存是共享内存区域,所有线程都可访问,但线程对变量的操作(读取赋值等)必须在工作内存中进行,首先要将变量从主内存拷贝到自己的工作空间,然后对变量进行操作,操作完成再将变量写回主内存,不能直接操作主内存中的变量,各个线程中的工作内存储存着主内存中的变量副本拷贝,因此不同的线程无法访问对方的工作内存,此案成间的通讯(传值) 必须通过主内存来完成
内存可见性:一个线程对共享变量的修改,能够及时的被其他线程看到
特点二:禁止指令重排
方式:内存屏障
写操作时:
在这里插入图片描述
读操作时:
在这里插入图片描述
特点3:不保证原子性
多个线程对同一个变量进行+1操作时,预期值达不到。
线程A从内存中拿到变量值1,然后线程A被阻塞,此时线程B也拿到变量值,由于没有被修改,所以线程B拿到的值也为1,进行+1操作,此时变量的值为2,此时A线程被唤醒,由于A线程已经读取过变量的值,所以继续在1的基础上进行+1操作。这样就会出问题。

2.AtomicInteger

可以解决volatile的原子性问题。
方式:CAS CompareAndSwap 比较并操作 unsafe类的native方法
下图是AtomicInteger的自增方法
传入三个参数,第一个是当前对象,第二个是内存地址偏移,第三个是+1
通过当前对象和内存地址偏移可以获得当前的值(var5),然后调用compareAndSwapInt方法,如果通过当前变量和地址偏移获取的值和var5(上面获取的)的值一致,就进行+1操作(var4的值为1),并返回true,取反返回false,退出循环,返回+1后的var5的值。
在这里插入图片描述
这里如果两个线程同时操作一个变量进行++操作,A线程拿到值1后阻塞,B线程也拿到值1进行+1操作,值变为2,此时A线程被唤醒,执行+1操作,此时A拿的值为1,但是compareAndSwapInt时发现从通过当前变量和地址偏移拿到的值为2,就不进行+1操作,必须再执行一次do中的操作,拿到最新的值,此时才能执行+1的操作。保证了原子性。

标签:变量,拿到,线程,内存,JUCJUC,操作,偏移
来源: https://blog.csdn.net/weixin_46666822/article/details/121443969

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有