JAVA并发编程(4):原子性操作以及CAS操作

发布时间:2022-06-26 发布网站:脚本宝典
脚本宝典收集整理的这篇文章主要介绍了JAVA并发编程(4):原子性操作以及CAS操作脚本宝典觉得挺不错的,现在分享给大家,也给大家做个参考。

一.原子性操作

所谓原子性操作,是指执行一系列操作时,这些操作要么全部执行,要么全部不执行,不存在执行其中一部分的情况。

如果不能保证操作是原子的,那么在多线程情况下,就有可能会存在线程安全问题。

接下来用代码来验证非原子操作在多线程环境下的线程安全问题:

public class ThreadSafetest {    PRivate static final LOGger LOGGER = LoggerFactory.getLogger(ThreadSafeTest.class);    private static int value = 0;    private static void increaseValue() {        for (int i = 0; i <100000;i++) {            value++;        }    }    public static void main(String[] args) throws InterruptedException {        Thread thread1 = new Thread(new Runnable() {            @override            public void run() {                increaseValue();            }        });        Thread thread2 = new Thread(new Runnable() {            @Override            public void run() {                increaseValue();            }        });        thread1.start();        thread2.start();        thread1.join();        thread1.join();        LOGGER.info("value:{}",value);    }}

第一次运行输出:

20:25:16.027 [main] INFO com.example.demo.ThreadSafeTest - value:125427

第二次运行输出:

20:28:17.946 [main] INFO com.example.demo.ThreadSafeTest - value:129915

可以看到两次运行结果都不等于两个线程加起来的循环次数200000,这就是非原子性操作在多线程环境下的线程安全问题。

&nbsp;

二.CAS操作

那么如何保证多个操作的原子性呢?最简单的办法是加锁,这里不讨论,除了加锁以外,还有一个更加轻量级的操作:CAS,CAS能够在不阻塞线程的情况下保证读-修改-写操作的原子性。

CAS即Compare And Swap,比较并交换,其是JDK提供的非阻塞原子性操作,底层通过硬件来保证比较-更新的原子性,主要包含三个步骤:

设在内存中有变量V,旧的预期值A,需要修改的新值B:

1.比较A与V是否相等;

2.如果相等,将B写入V;

3.返回操作是否成功;

这里认为A与V相等,则V没有被其他线程修改,否则认为V被其他线程修改过,将放弃这次修改,这个前提的存在也导致了ABA问题,暂不讨论。

JDK的Unsafe类提供了一系列的CAS操作,这里简单介绍

public final native boolean compareAndSwapLong(Object obj, long valueOffset, long expect, long update);

这个方法是native方法,由处理器保证该方法的原子性。

四个参数非别为:对象内存位置,对象中的变量偏移量,变量预期值以及变量新的值。

如果对象obj中内存偏移量为valueOffset的变量值为exPEct,则使用新的值update替换旧的值expect。

public final long getAndSetLong(Object VAR1, long var2, long var4) {
        long var6;
        do {
            var6 = this.getLongVolatile(var1, var2);
        } while(!this.COMpareAndSwapLong(var1, var2, var6, var4));

        return var6;
    }

该方法首先获取当前变量值,再使用CAS操作设置新的值,使用while循环是考虑到多线程同时修改时,CAS操作可能会失败,失败时将会重试。

 

JAVA并发包中的AtomicLong等原子操作类都是基于Unsafe提供的CAS操作实现的原子性操作,代码都很简单,不再记录。

脚本宝典总结

以上是脚本宝典为你收集整理的JAVA并发编程(4):原子性操作以及CAS操作全部内容,希望文章能够帮你解决JAVA并发编程(4):原子性操作以及CAS操作所遇到的问题。

如果觉得脚本宝典网站内容还不错,欢迎将脚本宝典推荐好友。

本图文内容来源于网友网络收集整理提供,作为学习参考使用,版权属于原作者。
如您有任何意见或建议可联系处理。小编QQ:384754419,请注明来意。