为了账号安全,请及时绑定邮箱和手机立即绑定

Java多线程i++线程安全问题,volatile和AtomicInteger解释?

Java多线程i++线程安全问题,volatile和AtomicInteger解释?

子衿沉夜 2019-03-12 11:14:00
在Java多线程中,i++和i--是非线程安全的。例子:public class PlusPlusTest {    public static void main(String[] args) throws InterruptedException {        Num num = new Num();        ThreadA threadA = new ThreadA(num);        ThreadB threadB = new ThreadB(num);        threadA.start();        threadB.start();        Thread.sleep(200);        System.out.println(num.count);    }}class ThreadA extends Thread {    private Num num;    public ThreadA(Num num) {        this.num = num;    }    @Override    public void run() {        for (int i = 0; i < 1000; i++) {            num.count++;        }    }}class ThreadB extends Thread {    private Num num;    public ThreadB(Num num) {        this.num = num;    }    @Override    public void run() {        for (int i = 0; i < 1000; i++) {            num.count++;        }    }}class Num {    int count = 0;    public Num() {    }}以上代码输出结果基本上不是2000,会比2000小。原因:在线程A中,i++的过程为:temp1 = i; temp2 = temp1 + 1; i = temp2;在线程B中,i++的过程为:temp3 = i; temp4 = temp3 + 1; i = temp4;在i=0的时候,线程A和B同时读取i=0。线程A执行++后,i被修改成1。线程B执行++后,i被修改,但还是1。问:这样的解释对么?想到把count变量申明为volatile,但是:即使把count申明为volatile,输出的结果也不是2000,请问为什么?class Num {    volatile int count = 0;    public Num() {    }}最后把count变量包装成AtomicInteger之后,输出的结果为2000,正确,这又是为什么?
查看完整描述

4 回答

?
料青山看我应如是

TA贡献1772条经验 获得超8个赞

因为volatile不保证操作的原子性,i++这种操作并不是原子操作。


查看完整回答
反对 回复 2019-04-24
?
慕的地8271018

TA贡献1796条经验 获得超4个赞

volatile只能保证可见性,即别人修改了之后你立马能读到,但是你改的时候别人也可以改。
AtomicInteger是基于CAS(Compare And Swap)的。

CAS有3个操作数,内存值V,旧的预期值A,要修改的新值B。当且仅当预期值A和内存值V相同时,将内存值V修改为B,否则什么都不做。 两个问题: (1)CAS算法仍然可能会出现冲突,例如A、B两个线程,A已经进入写内存但未完成,此时A读取到的副本且读取成功,AB两个线程同时进入写内存操作,必然会造成冲突。 CAS算法本质并非完全无锁,而是把获得锁和释放锁推迟至CPU原语实现,相当于尽可能的缩小了锁的范围;直接互斥地实现系统状态的改变,它的使用基本思想是copy-on-write——在修改完对象的副本之后再用CAS操作将副本替换为正本。 (2)ABA问题,若其中一个线程修改A->B->A,另外一个线程仍然读取到A,虽然值是预期值,但并不能说明该内存值没有变化。


查看完整回答
反对 回复 2019-04-24
?
慕慕森

TA贡献1856条经验 获得超17个赞

懒的写答案了,给一个非常好的文章Java并发编程:volatile关键字解析


查看完整回答
反对 回复 2019-04-24
?
慕桂英4014372

TA贡献1871条经验 获得超13个赞

volatile保证每次得到的数据是最新的(从内存中读取),i++; --> i=i+1; 如果执行到i+1没有赋值给i的话,就无法保证另个线程得到的数据是最新的,后面那个是原子操作,所以能够保证i=这一定会执行


查看完整回答
反对 回复 2019-04-24
  • 4 回答
  • 0 关注
  • 917 浏览

添加回答

举报

0/150
提交
取消
微信客服

购课补贴
联系客服咨询优惠详情

帮助反馈 APP下载

慕课网APP
您的移动学习伙伴

公众号

扫描二维码
关注慕课网微信公众号