Java多线程并发编程问答-No5

17 阅读3分钟

一.什么是CAS?

CAS是compare and swap的缩写,即我们所说的比较交换。

CAS是一种基于锁的操作,而且是乐观锁。在Java中锁分为乐观锁和悲观锁。悲观锁是将资源锁住,等一个之前获取锁的线程释放锁之后,下一个线程才可以访问。而乐观锁采用了一种宽泛的态度,通过某种方式不加锁来处理资源,比如通过给记录加version来获取数据,性能较悲观锁有很大的提高。

CAS操作包含三个操作数:内存位置(V)、预期原值(A)、和新值(B)。如果内存地址里面的值和A的值是一样的,那么就将内存里面的值更新成B。

CAS是通过无限循环来获取数据的,如果在第一轮循环中,a线程获取地址里面的值被b线程修改了,那么a线程需要自旋,到下次循环才有可能机会执行。

java.util.concurrent.atommic包下面的类大多是使用CAS操作来实现的(AtomicInteger,AtomicBoolean,AtomicLong)。

二.CAS 的问题

1.CAS容易造成ABA问题。

一个线程a将数值改成了b,接着又改成了a,此时CAS认为是没有变化,其实是已经变化过了,而这个问题的解决方案可以使用版本号标识,每次操作一次version加1.在Java5中,已经提供了AtomicStampedReference来解决问题。

2.不能保证代码块的原子性

CAS机制所保证的只是一个变量的原子性操作,而不是保证整个代码块的原子性。比如需要保证3个变量共同进行原子性的更新,就不得不使用synchronized了。

3.CAS造成CPU利用率增加

之前说过了CAS里面是一个循环判断的过程,如果线程一直没有获取到状态,CPU资源会一直被占用。

三.什么是Future?

在并发编程中,我们经常用到非阻塞的模型,在之前的多线程的三种实现中,不管是继承thread类还是实现runnable接口,都无法保证获取到之前的执行结果。通过实现Callback接口,并用Future可以来接收多线程的执行结果。

Future表示一个可能还没有完成的异步任务的结果,针对这个结果可以添加Callback以便在任务成功或失败后做出相应的操作。

四.什么是AQS?

AQS是AbustactQueuedSynchronizer的简称,它是一个Java提供的底层同步工具类,用一个int类型的变量表示同步状态,并提供了一系列的CAS操作来管理这个同步状态。

AQS是一个用来构建锁和同步器的框架,使用AQS能简单且高效地构造出应用广泛的大量同步器,比如我们提到的ReentrantLock,Semaphore,其他的诸如ReentrantReadWriteLock,SyncronousQueue,FutureTask等等都是基于AQS的。

五.AQS支持哪几种方式同步?

1.独占式

2.共享式

这样方便使用者实现不同类型的同步组件,独占式如ReentrantLock,共享式如Semaphore,CountDownLatch,组合式的如ReentrantReadWriteLock。

总之,AQS为使用提供了底层支撑。