1. CountDownLatch 计数器,需等待全部线程执行完毕,在向下执行。含有一个内部类Sync实现了AQS 的共享模式 没有公平非公平之分
理解:new CountDownLatch(10) new对象传的10会赋值给AQS的state 等待所有线程执行完毕向下执行,这里需要等待10线程全部执行完,每有一个线程执行完毕,执行一个减一操作
方法:
countDown() 每有一个线程执行完毕调用此方法,方法底层对AQS的state进行减一,然后利用CAS原理调用unsafe类(java操作内存的类)compareAndSwapInt方法修改state的值。当值减为0时,AQS中队列中等待线程才可以执行。
await()
调用此方法,方法底层会去检查AQS的state值是否等于0,等于0代表就可以直接执行了,不等于0就是还需要在等待,就会让当前线程进入AQS的队列中等待。
await(long timeout, TimeUnit unit)
相对于await()方法只有一个等待时间,在AQS队列中等待的时间。时间一到的话就不管了直接执行。
2. CyclicBarrier 跟CountDownLatch很类似,也是一个计数器类型,需全部线程都到位在一起执行。 内部使用ReentrantLock,Condition实现功能
理解:new CyclicBarrier(10) new对象设置parties,count为10,10为需要一起等待得线程数,通俗就是说要执行得10个线程同时到达同步点在一起执行。 new CyclicBarrier(10,Runable) 当有10条线程到达同步点,执行Runable
方法:
await()
调用此方法就是告诉Cyclicbarrier自己已经到达同步点。底层对count--,count-- == 0代表最后一个线程到达同步点,就会调用nextGeneration()。此方法会唤醒所有线程,将parties重新赋值给count。如果不是最后线程,就调用Condition.await()进行等待。
线程陷入等待状态,发现以下情况就会唤醒其他线程:
最后一个线程到达,即index == 0
某个参与线程等待超时
某个参与线程被中断
调用了CyclicBarrier的reset()方法。该方法会将屏障重置为初始状态
3. Semaphore 含有一个内部类Sync实现了AQS 的共享模式,有公平锁非公平锁之分。new对象传true创建公平锁,不传默认非公平锁。 (2,true)
理解:Semaphore在构造时,需要传入许可证的数量,它最后传递给了AQS的state值。线程在调用acquire方法获取许可证时,如果Semaphore中许可证的数量大于0,许可证的数量就减1,线程继续运行,当线程运行结束调用release方法时释放许可证时,许可证的数量就加1。如果获取许可证时,Semaphore中许可证的数量为0,则获取失败,线程进入AQS的等待队列中,等待被其它释放许可证的线程唤醒。
方法:
acquire() 获取许可证 线程获取许可证就会被阻塞,直到Semaphore中可以获得到许可证为止,然后线程再获取这个许可证。
release() 释放许可证 当调用release方法时将向Semaphore中添加一个许可证,如果有线程因为获取许可证被阻塞时,它将获取到许可证并被释放;如果没有获取许可证的线程, Semaphore只是记录许可证的可用数量。
公平锁:FairSync中多一个对阻塞队列是否有等待的线程的检查,如果没有,就可以参与许可证的竞争;如果有,线程直接被插入到阻塞队列尾节点并挂起,等待被唤醒。
非公平锁:当一个线程A调用acquire方法时,会直接尝试获取许可证,而不管同一时刻阻塞队列中是否有线程也在等待许可证,如果恰好有线程C调用release方法释放许可证,并唤醒阻塞队列中第一个等待的线程B,此时线程A和线程B是共同竞争可用许可证,不公平性就体现在:线程A没任何等待就和线程B一起竞争许可证了。