《Java并发编程的艺术》——并发工具类和AQS

2022-10-13 14:17:52

CountDownLatch(倒计时门闩)

允许一个或者多个线程等待其他线程完成操作(与join操作类似,join操作里实际调用的是wait方法),CountDownLatch初始化了一个int变量,每次调用countDown方法时这个变量都减1,await方法就是判断这个变量是否为0,如果为0就不阻塞了(门闩打开),不为0则调用countDown的线程阻塞(还被锁在门内)。

CyclicBarrier(回环屏障)

让多个线程到达同一状态(屏障)时被阻塞,直到最后一个线程也到达时,才打开屏障一起执行,构造方法的参数可以指定屏障要拦截的线程数量(每个线程调用await方法告诉CyclicBarrier我到达屏障了,被阻塞),如果想在所有线程到达屏障后执行一个动作(注意:这个动作是在打开屏障前,所有线程到达屏障后),可把这个动作写在构造函数的第二个参数里。
如果屏障设置数大与总的线程数,则屏障就永远无法打开,程序无法向下进行。
CyclicBarrier可以重用,CountDownLatch不能重用

Semaphore(信号量)

Semaphore通过取得(acquire方法)许可证(permit)的方式,控制同时访问资源的线程数量,访问完了线程通过release方法释放许可证,供其他线程获取。Semaphore经常用来控制并发数,限流。

Exchanger(交换者)

使用Exchanger的exchange方法,可以完成两个线程间的数据交换。
Exchanger提供了一个同步点,若第一个线程先执行exchange方法,会一直等待第二个线程执行,当二者都到达同步点了就交换数据,不然就一直等待。
若又超过2个线程使用同一exchanger,则随机2个线程会交换数据,剩下未交换数据的线程会一直等地啊。

AQS(AbstractQueuedSynchronizer)

AQS(AbstractQueuedSynchronizer)队列同步器,是用来构建ReentrantLock和上述并发工具的基本框架。AQS使用了一个volatile int state表示同步状态,state为1表示获得锁,为0表示释放资源,对于ReentrantLock的可重入表现为state的持续自增。AQS还使用了一个叫CLH的双向链表完成线程的排队工作,每一个结点表示了一个线程及其相关信息。
所有的并发工具和ReentrantLock都是重写了以下5个方法,完成锁的获取、释放和查看是否获得锁:

  • tryAcquire:尝试获取锁
  • tryRelease:尝试释放锁
  • tryAcquireShared:尝试获取共享锁
  • tryReleaseShared:尝试释放共享锁
  • isHeldExclusively:判断当前资源是不是线程独占状态

而以上5个方法是通过下列3个方法来获取、改变同步状态的:

  • getState
  • setState
  • compareAndSetState
  • 作者:Song X.
  • 原文链接:https://franksong.blog.csdn.net/article/details/99655984
    更新时间:2022-10-13 14:17:52