AQS就是基于CLH队列,用volatile修饰共享变量state,线程通过CAS去改变状态符,成功则获取锁成功,失败则进入等待队列,等待被唤醒
自旋锁是一种非阻塞锁,它的核心机制就在自旋两个字,即用自旋操作来替代阻塞操作。某一线程尝试获取某个锁时,如果该锁已经被另一个线程占用的话,则此线程将不断循环检查该锁是否被释放,而不是让此线程挂起或睡眠。一旦另外一个线程释放该锁后,此线程便能获得该锁。自旋是一种忙等待状态,过程中会一直消耗CPU的时间片。
互斥锁有一个很大的缺点,即获取锁失败后线程会进入睡眠或阻塞状态,这个过程会涉及到用户态到内核态的调度,上下文切换的开销比较大。假如某个锁的锁定时间很短,此时如果锁获取失败则让它睡眠或阻塞的话则有点得不偿失,因为这种开销可能比自旋的开销更大。
总结起来就是互斥锁更适合持有锁时间长的情况,而自旋锁更适合持有锁时间短的情况。
安全点,提供一个停止自旋锁的切入点,比如vm thread,在做线程dump, 内存 dump的时候,是需要让 自旋锁提前停止的
CountDownLatch没有提供任何机制去重新设置这个计数值。
典型的应用:并行计算,当某个任务需要处理运算量非常大,可以将该运算任务拆分为多个子任务,等待所有的子任务完成之后,父任务再拿到所有子任务的运算结果进行汇总。
Semaphore经常用于限制获取某种资源的线程数量,其内部是基于AQS的共享模式,AQS的状态表示许可证的数量,在许可证数量不够时,线程将会被挂起;而一旦有一个线程释放一个资源,那么就有可能重新唤醒等待队列中的线程继续执行。
使用场景:
适合控制并发数,可以用于做流量控制,特别公用资源有限的应用场景,比如数据库连接
CyclicBarrier允许一组线程相互之间等待,达到一个共同点,再继续执行。与CountDownLatch比较
相同点:
都是同步辅助类。
使用计数器实现
不同点:
CountDownLatch允许一个或多个线程,等待其他一组线程完成操作,再继续执行。
CyclicBarrier允许一组线程相互之间等待,达到一个共同点,再继续执行。
CountDownLatch不能被复用
CyclicBarrier适用于更复杂的业务场景,如计算发生错误,通过重置计数器,并让线程重新执行
CyclicBarrier还提供其他有用的方法,比如getNumberWaiting方法可以获得CyclicBarrier阻塞的线程数量。isBroken方法用来知道阻塞的线程是否被中断。