CAS问题

来源:3-2 线程安全性-原子性-atomic-2

慕码人1464173

2019-01-31

public final int getAndAddInt(Object var1, long var2, int var4) {
        int var5;
        do {
	        // var5主内存中的值,var1是线程工作内存中的值
            var5 = this.getIntVolatile(var1, var2);
        } while(!this.compareAndSwapInt(var1, var2, var5, var5 + var4));
        return var5;
    }

var5主内存中的值,var1是线程工作内存中的值,比较的是var1.value和var5是否相同,不同继续获取主内存中的值与线程工作内存中的值比较。问题:假设var1是3,主内存中的值被其他线程操作自增变为4,5,6 … 这边是不是会一直循环下去,直到主内存中的值同步到线程工作内存中,且没有其他线程操作?还是说这里面哪一步是有同步工作内存和主内存的操作?

写回答

2回答

Jimin

2019-01-31

继续看 compareAndSwapInt(obj, offset, expect, update)能清楚一些,如果obj内的value和expect相等,就证明没有其他线程改变过这个变量,那么就更新它为update,如果不相等返回false,调用getIntVolatile获取内存里最新的值给expect的,之后函数里的update也跟着变了,再去尝试cas更新,只要这两步过程中没其他线程操作,就会或许成功,极端情况下就是这两步过程中有其他操作,需要再重试一次。因为每次是取最新值去尝试,cas处理时只要和内存一致就更新,其实并不会出现无限循环,并发很高时也会很快结束

0
2
Jimin
回复
慕码人1464173
3会同步为最新的值。你的如果有点问题,每次都是取的内存里最新值,只是取出内存里的值(getIntVolatile)与cas操作(compareAndSwapInt)是两个操作,保证不了原子性,因此可能更新时因为有其他线程的操作导致更新失败。失败会取出内存里最新值(expect和update都会跟着变)重新来一次就好了
2019-02-01
共2条回复

Jimin

2019-01-31

你好,这篇手记 https://www.imooc.com/article/25277 我做了一些问题的整理,包括cas,你这个我单独复制出来:

关于CAS中compareAndSwapInt(var1, var2, var5, var5 + var4)的理解
compareAndSwapInt(var1, var2, var5, var5 + var4)换成 compareAndSwapInt(obj, offset, expect, update)能清楚一些,如果obj内的value和expect相等,就证明没有其他线程改变过这个变量,那么就更新它为update,如果这一步CAS没有成功,那就采用自旋的方式继续进行CAS操作。这块是一个CPU指令完成的,依旧是原子操作。

继续回答一下你的疑问。这里不会出现死循环。因为对比和更新的操作是通过一条cpu指令执行的,如果期望值检查通过更新了的话会返回true,循环就直接退出了。如果期望值检查不通过没更新会返回false,这是更新期望值为最新的值,再尝试更新,直到返回true。

上面的代码里getIntVolatile会强制去内存中获取最新的数据

0
1
慕码人1464173
老师,手记我看过的,我还是疑问:如果返回false,会更新期望值,那obj会同步更新吗?因为obj与期望值不同的原因可能之间有线程做了更改,如果obj不变的话,一直循环获取最新的期望值,最后也不会与obj相等吧。有没有调试多线程环境的方法,比如debug之类的?
2019-01-31
共1条回复

Java高并发编程,构建并发知识体系,提升面试成功率

构建完整并发与高并发知识体系,倍增高薪面试成功率!

3923 学习 · 832 问题

查看课程