[源码]Concurrent包之信号量

来源:互联网 发布:航空大亨4无法连接网络 编辑:程序博客网 时间:2024/05/21 15:47

CountDownLatch

计数器,适合于多线程倒数。不得不说,这种300多行,没什么算法的类还是比较适合我的。
内部使用了一个AbstractQueuedSynchronizer记录Count。AbstractQueuedSynchronizer是一个维持一个线程安全state和等待队列的基础类。

AbstractQueuedSynchronizer

算法(又是算法)是CLH队列锁。实现和原理基本一致,线程安全靠CAS,有一个非常好的点,只保证可以被操作数据的线程安全,即tail和head的线程安全,其他field一概忽略。这样做,是用开发的思考时间换代码执行效率。等待使用了LockSupport#park/unpark,主要是可以指定等待和释放的线程。

CyclicBarrier

是一个全局同步锁,可以看做每个线程执行完成都对CountDownLatch - 1,所有线程都wait这个CountDownLatch,特色是能够制定一个后续行为(Action),还能重复利用。
核心就是dowait函数了。用的是ReentrantLock+Condition#wait,并没有复杂算法。做的非常好的地方就是,为了重用方便,把重用时变化的field都封装到了一个类(Generation)里,每次重用只需要new一个新对象,需要关心的状态就是全新的了(但是parties,等待数并没有在Generation里)。

Exchanger

也算在信号量里吧,用于两个线程互换数据,当然会有等待。可以认为是两个Future#get的作用,或者是两个SynchronizeQueue。算法呢分为两种Slot和Arena。

  • Slot较SynchronizeQueue更简单,因为是一次性的匹配,核心思想跟SynchronizeQueue是一样的。用一个Slot(Transfer)封装一个数据提交,如果没人exchange过就CAS并等待,否则就取一下Slot然后返回。但是扩展性不好,所以有了Arena
  • Arena其实就是映射到多个Slot上,减少竞争

Semaphore

PV操作了,也是基于AbstractQueuedSynchronizer,其实就是线程安全计数。分为公平和不公平信号量。

  • 公平:来了就判断可不可以拿到权限,可以就返回
  • 不公平:先判断AbstractQueuedSynchronizer内是否有先来者,先来先释放

ReentrantLock

state为1的Semaphore,整个实现基本一模一样。也分为公平和不公平锁。

ReentrantReadWriteLock

还是用AbstractQueuedSynchronizer,读锁用aquireShared,写锁用aquire

0 0
原创粉丝点击