JDK 5 的并发包中提供了不少类,这些类提供了比原有的并发机制更好的性能和伸缩性。要想理解这些类的工做机理,那就不得不提到 CAS。CAS 全称是 Compare and Swap,是指现代主流 CPU 都支持的一种指令,这个指令能为多线程编程带来更好的性能(稍后会详细介绍)。另一个可能会被当作 CAS 的是 Compare and Set,是指 JDK 5 并发包中普遍使用的一种基于 Compare and Swap 的并发算法。严格说 CAS 仅指代前者。算法
在这里,CAS 指的是现代 CPU 普遍支持的一种对内存中的共享数据进行操做的一种特殊指令。这个指令会对内存中的共享数据作原子的读写操做。简单介绍一下这个指令的操做过程:首先,CPU 会将内存中将要被更改的数据与指望的值作比较。而后,当这两个值相等时,CPU 才会将内存中的数值替换为新的值。不然便不作操做。最后,CPU 会将旧的数值返回。这一系列的操做是原子的。它们虽然看似复杂,但倒是 Java 5 并发机制优于原有锁机制的根本。简单来讲,CAS 的含义是“我认为原有的值应该是什么,若是是,则将原有的值更新为新值,不然不作修改,并告诉我原来的值是多少”(这段描述引自《Java Concurrency in Practice》)编程
在理解了什么是 Compare and Swap 以后,理解 Compare and Set 便很容易了。Compare and Set 就是利用 Compare and Swap 实现的非阻塞的线程安全的写操做算法。它的实现过程以下:首先读取你要更改的数据的原值,而后将其和你要更新成的值做为 Compare and Swap 操做的两个参数,若是 Compare and Swap 的返回值和原值不一样,便重复这一过程,直至成功。写成伪代码以下安全
int old; int new; do { old = value.get(); new = doSomeCalcBasedOn(old) while (value.compareAndSwap(old, new));
Compare and Set 是一个非阻塞的算法,这是它的优点。可是有一个问题就是存在这样的可能,在每次读操做以后,写操做以前,都有另一个线程更改了原先的值,这样 Compare and Set 操做就会不停地重试。但这样的可能只存在于理论,在实际中不多发生。多线程
Compare and Set 普遍使用在 Java 5 中的 Atomic 类中,其它的诸如 ReetrantLock、Semaphore 等的类也经过 AbstractQueuedSynchronizer 类间接地使用了 Compare and Set。并发