CAS

cas是无锁优化,或者叫自旋。通过Atomic类来实现。

由于一些常见的操作,加锁的情况特别多,所以java提供了这些类,内部自带了锁,当然这些锁不是由synchronized来实现的,而是通过cas的操作实现的。

public class study04 {

    public static void main(String[] args) {

        study04 study =new study04();

        List threads =new ArrayList<>();

        for (int i=0; i <10; i++){

            threads.add(new Thread(study :: m, "thread-"+i));

        }

        threads.forEach(o -> o.start());

        threads.forEach(o -> {

            try {

                o.join();

            }catch (InterruptedException e) {

                e.printStackTrace();

            }

        });

        System.out.println(study.count);

    }

    AtomicIntegercount =new AtomicInteger(0);

    void m(){

        for (int i =0; i <10000; i ++){

        count.incrementAndGet();

        }

    }

}

count.incrementAndGet()的内部实现:

public final int incrementAndGet() {

    return unsafe.getAndAddInt(this, valueOffset, 1) +1;

}

public final int getAndAddInt(Object var1, long var2, int var4) {

    int var5;

    do {

        var5 =this.getIntVolatile(var1, var2);

    }while(!this.compareAndSwapInt(var1, var2, var5, var5 + var4));

    return var5;

}

compareAndSwapInt:

cas(V, Expected, NewValue)

    if V == Expected

        V = NewValue

        otherwise try again or fail

V是要修改的值,Expected是期望值,NewValue是新值,如果要修改的值等于期望值,那么代表没有其他线程修改过它,可以设定新值,否则代表有其他线程修改过值,那么cas要重新尝试读取期望值。cas操作是cpu原语级的,中间不允许被打断,是原子性的。

CAS修改的如果是对象会导致ABA问题。线程A发现对象(Expected)的引用还是原来的引用,就允许修改,但其实该对象可能已经被线程B修改过值并重新引用到原来的对象上,线程A无法发现。要解决ABA问题需要引入版本号,compare的时候连版本号一起比较。

CAS是通过Unsafe这个类来实现的。

©著作权归作者所有,转载或内容合作请联系作者
【社区内容提示】社区部分内容疑似由AI辅助生成,浏览时请结合常识与多方信息审慎甄别。
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

相关阅读更多精彩内容

友情链接更多精彩内容