Basic Of Concurrency(二十: Compare And Swap)

CAS(Compare And Swap)比较和替换经常使用于设计并发算法.一般的作法是将预期值和一个确切的变量相比较,若是相等,则将变量替换为新的值.CAS并无想象中的复杂,只要你理解了其实特别的简单.html

什么样的场景中能够用到CAS

在并发算法和程序中“先检查后执行”是一个很常见的模式.即先检查一个变量值而后基于这个变量值执行.以下所示:java

class MyLock {

    private boolean locked = false;

    public boolean lock() {
        if(!locked) {
            locked = true;
            return true;
        }
        return false;
    }
}
复制代码

这段代码在并发环境中会有线程安全问题,在这里咱们先忽略这点.算法

咱们能够看到,在lock()方法中,首先去检查变量locked是否为false(先检查),若是是的话则将它设置为true(后执行).安全

若是多个线程同时调用同个MyLock实例,上面的lock()方法将不能保证是线程安全的.若是线程A此时检查变量locked发现它为false,同时线程B也可以对locked进行检查.事实上只要线程A在没有设置locked变量为false以前,其余线程都能对locked变量进行检查.因此线程A和B都能检查和发现locked变量为false,而且都能在此之上执行.多线程

为了确保在多线程应用中是线程安全的,“先检查后执行”操做必须是原子的.原子的意思是检查和执行必须在同一个原子代码块中执行,而不能分开.任何一个线程在执行原子代码块的过程当中都不会受到其余线程的干扰直到结束为止.没有线程能在同一时间执行原子代码块.并发

下面将上文说起的实例更改成使用synchronized关键字实现的原子代码块.post

class MyLock {

    private boolean locked = false;

    public synchronized boolean lock() {
        if(!locked) {
            locked = true;
            return true;
        }
        return false;
    }
}
复制代码

如今lock()方式已是同步的了,因此同一时间只能有一个线程可以在Mylock实例上执行.lock()方法一样已是原子的了.性能

原子版的lock()方法已是一个活生生的“比较和替换”的例子了.lock()方法先比较变量locked是否为预期值false,若是是的话,则将变量替换为true.atom

CAS即原子操做

现代CPU大部分已经内建支持原子的比较和替换操做.在Java5中,你可使用java.util.concurrent.atomic包中的原子对象来使用CPU中的这些功能.spa

下面示例了上文lock()方法如何使用AtomicBoolean对象.

public static class MyLock {
    private AtomicBoolean locked = new AtomicBoolean(false);

    public boolean lock() {
        return locked.compareAndSet(false, true);
    }

}
复制代码

咱们能够注意到locked已经不是基础布尔类型,而是AtomicBoolean类型.这个对象有一个compareAndSet()方法用于比较AtomicBoolean实例值,若实例值等于一个预期值,则将它替换为新的值.在例子中,咱们将比较locked值是否为false,若是是则将它替换为true.

compareAndSet()方法若是成功替换值则返回true,不然返回false.

使用Java5+中所提供原子对象的CAS功能,比起你本身实现的CAS带来的优点是可以使用CPU中的比较和替换特性.这比本身实现的CAS性能要优越得多.

该系列博文为笔者复习基础所著译文或理解后的产物,复习原文来自Jakob Jenkov所著Java Concurrency and Multithreading Tutorial

上一篇: 线程池
下一篇: 分析一个同步装置

相关文章
相关标签/搜索