Java并发编程之CAS算法

来源:互联网 发布:在c语言中拆分英文名 编辑:程序博客网 时间:2024/04/29 19:12

在多线程环境下,我们要实现对一个变量自增的话,往往会使用java.util.concurrent.atomic包下的相关实现类。 如下:

public class TestAtomic {    public static void main(String[] args) {        ThreadDemo td=new ThreadDemo();        //开启二十个线程完成自加操作        for(int x=1;x<=20;x++){            new Thread(td).start();        }    }}class ThreadDemo implements Runnable {    //定义一个AtomicInteger的初始值为0的变量atoInt    private AtomicInteger atoInt=new AtomicInteger(0);    @Override    public void run() {        try {            //休眠一下,提高并发性            Thread.sleep(200);        } catch (InterruptedException e) {            e.printStackTrace();        }        System.out.println(getNum());    }    public int getNum() {        //每次返回的为当前值的下一个值        return atoInt.incrementAndGet();    }}

这里用到原子并发包装类
1:对于变量,原子性操作都用到了volatile关键字,确保线程之间的可见性。
2:用到了CAS(Compare and Swap)算法


CAS算法
这里用到的主要有三个值
主存值 V :从主存中取出值
预估值 A :对于非原子性的操作,再进行下一次计算操作之前,会再次读取主存中的值
更新值 B :根据具体的逻辑,有待跟新的值
这里有关主存的问题,可以参考 这篇文章,在CAS算法中,如果 V==A 则把B的值复制给V,否则什么也不做,并进行下一次尝试。

     *  比如 对于     *  int num=0;     *  i=num++;这个操作     *  在进行num++这个操作的时候,先从主存中获取num的值,然后再进++操作     *  很明显这是两个步骤,在获取num的值之后,另一个线程可能已经更改了num的值,这时候加的时候明显有问题     *  CAS算法如下:     *  获取主存值 V=0     *  执行之后,在查看一个主存的值 此时如果还是 A=0(没有线程修改)     *  根据num++的操作,此时B应该更新到值为0+1=1     *  V=0     *  A=0     *  B=1     *  因为V==A 此时把B的值刷新到主存中V=1;     *  ************************************************     *  如果在一个线程读取之后,另一个线程修改了值,即A=1     *  V=0               *  A=1              *  B=1              *  V!=A,则不会把B的值刷新到主存中     */

Java并发之CountDownLatch