JUC三个并发锁CountDownLatch、CyclicBarrier、Semaphore示范和解释
三个都位于java.util.concurrent下,并发锁,内部都是利用抽象类Sync实现的,做计数器的时候使用的CompareAndSet对Sync内部的成员变量整数state做增减实现,另外支持公平锁和非公平锁,默认是非公平锁NonFairSync
CountDownLatch 计数器锁
线程来调用countdown()让计数器递减(CAS,CompareAndSet),直到0的时候await()函数堵塞的会被放行
package lock;
import java.util.concurrent.CountDownLatch;
/**
* CountDownLatchDemo 示范
* 构造方法传入一个计数器
* countdown()让计数器减1
* 直到计数器被减到0时 await()的等待会被放行
*/
public class CountDownLatchDemo {
public static void main(String[] args) {
CountDownLatch countDownLatch = new CountDownLatch(2);
Thread thread = new Thread(()->{
try {
countDownLatch.await();
System.out.println(Thread.currentThread().getName()+"通过countdown锁,执行代码");
}catch (Exception e){
e.printStackTrace();
}
},"thread");
Thread t1 = new Thread(()-> {
try {
Thread.sleep(1000);
countDownLatch.countDown();
System.out.println(Thread.currentThread().getName()+"执行了countdown");
}catch (Exception e){
e.printStackTrace();
}
},"t1");
Thread t2 = new Thread(()-> {
try {
countDownLatch.countDown();
System.out.println(Thread.currentThread().getName()+"执行了countdown");
}catch (Exception e){
e.printStackTrace();
}
},"t2");
thread.start();
t1.start();
t2.start();
}
}
CyclicBarrier 循环珊栏锁
线程来调用await()声明自己已经执行到了珊栏等待其他线程到了再执行,让计数器递减(CAS,CompareAndSet),直到0的时候该堵塞的所有线程全部会被放行
package lock;
import java.util.Random;
import java.util.concurrent.CyclicBarrier;
/**
* 循环珊栏示范
* 构造方法传入总共要等几个线程await才能通过珊栏
* await()告知锁我已经到达珊栏进行等待了
* 一旦要求的所有线程到达了珊栏进行等待即可放行通过,通过后珊栏会被自动重置掉,能循环使用
*/
public class CyclicBarrierDemo {
public static void main(String[] args) {
Random random = new Random();
CyclicBarrier cyclicBarrier = new CyclicBarrier(2);
Thread t1 = new Thread(()->{
for (;;){
try {
Thread.sleep(random.nextInt(1000));
System.out.println(Thread.currentThread().getName()+"等待");
cyclicBarrier.await();
System.out.println(Thread.currentThread().getName()+"越过了珊栏,执行");
}catch (Exception e){
e.printStackTrace();
}
}
},"t1");
Thread t2 = new Thread(()->{
for (;;){
try {
Thread.sleep(random.nextInt(1000));
System.out.println(Thread.currentThread().getName()+"等待");
cyclicBarrier.await();
System.out.println(Thread.currentThread().getName()+"越过了珊栏,执行");
}catch (Exception e){
e.printStackTrace();
}
}
},"t2");
t1.start();
t2.start();
}
}
Semaphore 信号量锁
线程来调用aquire()让计数器递减(CAS,CompareAndSet),拿到了信号量就返回了继续执行,如果没拿到可以一直堵塞在那等待拿到才继续执行,另外也可以手动调用release()来添加信号量,让计数器自增。
package lock;
import java.util.Random;
import java.util.concurrent.Semaphore;
/**
* Semaphore信号量锁示范
* 构造方法传入总共多少个信号量
* acquire()请求拿一个信号量
* release()添加一个信号量
*/
public class SemaphoreDemo {
public static void main(String[] args) {
Random random = new Random();
Semaphore semaphore = new Semaphore(2);
Thread t1 = new Thread(()->{
for (;;){
try {
Thread.sleep(random.nextInt(2000));
System.out.println(Thread.currentThread().getName()+"等待");
semaphore.acquire();
System.out.println(Thread.currentThread().getName()+"获得了信号量,执行代码");
Thread.sleep(random.nextInt(2000));
System.out.println(Thread.currentThread().getName()+"执行完了代码,释放信号量");
semaphore.release();
}catch (Exception e){
e.printStackTrace();
}
}
},"t1");
Thread t2 = new Thread(()->{
for (;;){
try {
Thread.sleep(random.nextInt(2000));
System.out.println(Thread.currentThread().getName()+"等待");
semaphore.acquire();
System.out.println(Thread.currentThread().getName()+"获得了信号量,执行代码");
Thread.sleep(random.nextInt(2000));
System.out.println(Thread.currentThread().getName()+"执行完了代码,释放信号量");
semaphore.release();
}catch (Exception e){
e.printStackTrace();
}
}
},"t2");
t1.start();
t2.start();
}
}