浅析CAS(Compare and Swap)

什么叫CAS(Compare and Swap)? 

    根据英文全称翻译,CAS即比较与交换。

    有啥用处?

    对于常用多线程编程的人估计知道,对于一般人估计都不曾听说。在jdk5之前,我们知道,在多线程编程的时候,为了保证多个线程对一个对象同时进行访问时,我们需要加同步锁synchronized,保证对象的在使用时的正确性,但是加锁的机制会导致如下几个问题

    1.加多线程竞争下,加锁和释放锁会导致较多的上下文切换,引起性能问题。

    2.多线程可以导致死锁的问题。

    3.多线程持有的锁会导致其他需要此锁的线程挂起。

    4......

    有更好的办法么?

    锁的分类:独占锁(悲观锁),乐观锁

    独占锁:synchronized就是一种独占锁,它会导致所有需要此锁的线程挂起,等待锁的释放。

    乐观锁:每次不加锁去完成操作,如果因为冲突失败就重试,直到成功。

    CAS的机制就相当于这种(非阻塞算法),CAS是由CPU硬件实现,所以执行相当快。CAS有三个操作参数:内存地址,期望值,要修改的新值,当期望值和内存当中的值进行比较不相等的时候,表示内存中的值已经被别线程改动过,这时候失败返回,当相等的时候,将内存中的值改为新的值,并返回成功。

------------------------------------------------------  我是分割线  ------------------------------------------------------ 

现在用两个例子来展示使用CAS的机制后和没有线程安全时的区别:

例子1:非线程安全的示例:

public class UnSafeTest {

	private static Integer a = new Integer(1);

    public static void main(String[] args) {
        
    	final CountDownLatch latch = new CountDownLatch(10);
    	for (int i = 1; i <= 10; i++){
            new Thread(new Runnable() {
                public void run() {
                    //启动10个线程,每个线程打印加1之后的值              	
                	System.out.println(a++);
                	latch.countDown();
                }
            }).start();
        }
    	try {
			latch.await();
			System.out.println("最终的值:" + a);
		} catch (InterruptedException e) {
			e.printStackTrace();
		}
    }	
}

输出结果:

1
1
1
1
1
2
3
4
5
6
最终的值:7

可以看见,最终值并不是预期中的10,当然每次运行结果都不一致,人品爆发的时候是可以拿到10的。

而经CAS的机制的改造后,可以把上面的例子变成线程安全的。

例子2:

public class SafeTest {

	private static AtomicInteger a = new AtomicInteger(0);

    public static void main(String[] args) {
        
    	final CountDownLatch latch = new CountDownLatch(10);
    	for (int i = 0; i < 10; i++){
            new Thread(new Runnable() {
                public void run() {
                    //启动10个线程,每个线程打印加1之后的值              	
                	System.out.println(a.incrementAndGet());
                	latch.countDown();
                }
            }).start();
        }
    	try {
			latch.await();
			System.out.println("最终的值:" + a);
		} catch (InterruptedException e) {
			e.printStackTrace();
		}
    }	
}

输出结果:

1
2
3
4
5
6
7
8
9
10
最终的值:10
得到期待值10。


猜你喜欢

转载自blog.csdn.net/qq9808/article/details/80340558