CAS(Compare and swap)比较和替换是设计并发算法时用到的一种技术。简单来说,比较和替换是使用一个期望值和一个变量的当前值进行比较,如果当前变量的值与我们期望的值相等,就使用一个新值替换当前变量的值。这听起来可能有一点复杂但是实际上你理解之后发现很简单,接下来,让我们跟深入的了解一下这项技术。

CAS的使用场景

在程序和算法中一个经常出现的模式就是“check and act”模式。先检查后操作模式发生在代码中首先检查一个变量的值,然后再基于这个值做一些操作。下面是一个简单的示例:

01 class MyLock {
02  
03     private boolean locked = false;
04  
05     public boolean lock() {
06         if(!locked) {
07             locked = true;
08             return true;
09         }
10         return false;
11     }
12 }

上面这段代码,如果用在多线程的程序会出现很多错误,不过现在请忘掉它。

如你所见,lock()方法首先检查locked>成员变量是否等于false,如果等于,就将locked设为true。

如果同个线程访问同一个MyLock实例,上面的lock()将不能保证正常工作。如果一个线程检查locked的值,然后将其设置为false,与此同时,一个线程B也在检查locked的值,又或者,在线程A将locked的值设为false之前。因此,线程A和线程B可能都看到locked的值为false,然后两者都基于这个信息做一些操作。

为了在一个多线程程序中良好的工作,”check then act” 操作必须是原子的。原子就是说”check“操作和”act“被当做一个原子代码块执行。不存在多个线程同时执行原子块。

下面是一个代码示例,把之前的lock()方法用synchronized关键字重构成一个原子块。

01 class MyLock {
02  
03     private boolean locked = false;
04  
05     public synchronized boolean lock() {
06         if(!locked) {
07             locked = true;
08             return true;
09         }
10         return false;
11     }
12 }

现在lock()方法是同步的,所以,在某一时刻只能有一个线程在同一个MyLock实例上执行它。

原子的lock方法实际上是一个”compare and swap“的例子。

CAS用作原子操作

现在CPU内部已经执行原子的CAS操作。Java5以来,你可以使用java.util.concurrent.atomic包中的一些原子类来使用CPU中的这些功能。

下面是一个使用AtomicBoolean类实现lock()方法的例子:

1 public static class MyLock {
2     private AtomicBoolean locked = new AtomicBoolean(false);
3  
4     public boolean lock() {
5         return locked.compareAndSet(false, true);
6     }
7  
8 }

locked变量不再是boolean类型而是AtomicBoolean。这个类中有一个compareAndSet()方法,它使用一个期望值和AtomicBoolean实例的值比较,和两者相等,则使用一个新值替换原来的值。在这个例子中,它比较locked的值和false,如果locked的值为false,则把修改为true。

如果值被替换了,compareAndSet()返回true,否则,返回false。

使用Java5+提供的CAS特性而不是使用自己实现的的好处是Java5+中内置的CAS特性可以让你利用底层的你的程序所运行机器的CPU的CAS特性。这会使还有CAS的代码运行更快。

Java并发编程之CAS的更多相关文章

  1. Java并发编程之CAS第一篇-什么是CAS

    Java并发编程之CAS第一篇-什么是CAS 通过前面几篇的学习,我们对并发编程两个高频知识点了解了其中的一个—volatitl.从这一篇文章开始,我们将要学习另一个知识点—CAS.本篇是<凯哥 ...

  2. Java并发编程之CAS二源码追根溯源

    Java并发编程之CAS二源码追根溯源 在上一篇文章中,我们知道了什么是CAS以及CAS的执行流程,在本篇文章中,我们将跟着源码一步一步的查看CAS最底层实现原理. 本篇是<凯哥(凯哥Java: ...

  3. Java并发编程之CAS第三篇-CAS的缺点及解决办法

    Java并发编程之CAS第三篇-CAS的缺点 通过前两篇的文章介绍,我们知道了CAS是什么以及查看源码了解CAS原理.那么在多线程并发环境中,的缺点是什么呢?这篇文章我们就来讨论讨论 本篇是<凯 ...

  4. Java高性能编程之CAS与ABA及解决方法

    Java高性能编程之CAS与ABA及解决方法 前言 如果喜欢暗色调的界面或者想换换界面,可以看看我在个人博客发布的 Java高性能编程之CAS与ABA及解决方法. CAS概念 CAS,全称Compar ...

  5. Java并发编程之set集合的线程安全类你知道吗

    Java并发编程之-set集合的线程安全类 Java中set集合怎么保证线程安全,这种方式你知道吗? 在Java中set集合是 本篇是<凯哥(凯哥Java:kagejava)并发编程学习> ...

  6. Java并发编程之AQS

    一.什么是AQS AQS(AbstractQueuedSynchronize:队列同步器)是用来构建锁或者其他同步组件的基础框架,很多同步类都是在它的基础上实现的,比如常用的ReentrantLock ...

  7. Java 并发编程之 Condition 接口

    本文部分摘自<Java 并发编程的艺术> 概述 任意一个 Java 对象,都拥有一个监视器方法,主要包括 wait().wait(long timeout).notify() 以及 not ...

  8. Java并发编程之Lock

    重入锁ReentrantLock 可以代替synchronized, 但synchronized更灵活. 但是, 必须必须必须要手动释放锁. try { lock.lock(); } finally ...

  9. Java并发编程之synchronized关键字

    整理一下synchronized关键字相关的知识点. 在多线程并发编程中synchronized扮演着相当重要的角色,synchronized关键字是用来控制线程同步的,可以保证在同一个时刻,只有一个 ...

随机推荐

  1. 关于如何在BCB中使用CodeGuard

    作者:深圳虫 来自:深圳虫网本文来自http://www.szbug.com/disparticle.aspID=4 一. 为什么写这篇东西自己在使用BCB5写一些程序时需要检查很多东西,例如内存泄漏 ...

  2. C 函数原型

    int add(int,int);//add two int numbers and return it--- add function prototype; int main(int argc, c ...

  3. NodeJS制作爬虫全过程

    这篇文章主要介绍了NodeJS制作爬虫的全过程,包括项目建立,目标网站分析.使用superagent获取源数据.使用cheerio解析.使用eventproxy来并发抓取每个主题的内容等方面,有需要的 ...

  4. 线性规划||网络流(费用流):COGS 288. [NOI2008] 志愿者招募

    [NOI2008] 志愿者招募 输入文件:employee.in   输出文件:employee.out   简单对比 时间限制:2 s   内存限制:512 MB [问题描述] 申奥成功后,布布经过 ...

  5. 【模拟】Codeforces 710A King Moves

    题目链接: http://codeforces.com/problemset/problem/710/A 题目大意: 国际象棋标准8X8棋盘,国王能往周围8个方向走.输入国王的位置,输出当前国王能往几 ...

  6. OpenGL图形管线和坐标变换

    转:http://blog.csdn.net/zhulinpptor/article/details/5897102 1. OpenGL 渲染管线 OpenGL渲染管线分为两大部分,模型观测变换(Mo ...

  7. qemu kvm 虚拟化

    虚拟化: KVM是一个基于Linux内核的虚拟机,属于完全虚拟化.虚拟机监控的实现模型有两类:监控模型(Hypervisor)和宿主机模型(Host-based).由于监控模型需要进行处理器调度,还需 ...

  8. winscp自动执行脚本

    我们经常使用WinSCP工具通过sftp协议上传获取文件,本文描述通过bat批量处理文件. 首先,我们打开dos命令窗口使用 cd \d :D\WinSCP 打开WinSCP安装目录 上传文件: wi ...

  9. linux内网机器访问外网代理设置squid

    公司一般出于安全考虑, 在同一局域网中只有一台机器可以访问外网,运维进行了整体的限制, 但是在后面的工作中,需要在机器上安装一些软件,及命令,所以其他的机器需要访问外网来简化工作, 但又不能打乱原有运 ...

  10. OpenRisc-43-or1200的IF模块分析

    引言 “喂饱饥饿的CPU”,是计算机体系结构设计者时刻要考虑的问题.要解决这个问题,方法大体可分为两部分,第一就是利用principle of locality而引进的cache技术,缩短取指时间,第 ...