简单介绍AQS、ReetrantLock、CountDownLatch、CyclicBarrier、Semaphore

AQS,既AbstractQueuedSynchronizer, 是JUC包实现同步的基础工具,是一个抽象类。

在AQS中,定义了一个volatile int state变量作为共享资源,并且内置自旋锁实现的同步队列,封装入队和出队的操作,提供独占、共享、中断等特性的方法。

如果线程获取资源失败,则进入同步FIFO(先进先出)队列中等待(入队);
如果成功获取资源就执行临界区代码。
执行完释放资源时,通知队列中的等待线程来获取资源,然后出队。

AQS的子类可以定义不停的资源实现不同性质的方法

ReetrantLock

可重入锁。定义state为0时可以获取资源并置为1.若已获得资源,state不断地+1,在释放资源时state-1,直至为0

CountDownLatch

CountDownLatch也是juc包中的一个类,类似倒计时计数器,初始时定义了资源总量state=count,调用await()方法则处于等待状态。countDown()不断地将state-1,当state=0时才能获得锁,所有线程都不会等待。

使用场景:
将主线程阻塞,等异步的多线程全部执行完毕并返回结果后,再继续执行主线程。

public static List<String> getExecutorService() throws InterruptedException{
		System.out.println("开始执行多线程...");
		long startTime = System.currentTimeMillis();
		List<String> list = new CopyOnWriteArrayList<>();//存放返回结果
		CountDownLatch countDownLatch = new CountDownLatch(10);
		ExecutorService executorService = Executors.newFixedThreadPool(10);
		for (int i = 0; i < 10; i++) {
			Runnable runnable = new Runnable(){
 
				@Override
				public void run() {
					 try {
						Thread.sleep(3000);
                        list.add(UUID.randomUUID().toString());
                        System.out.println("当前线程name : "+Thread.currentThread().getName());
                        countDownLatch.countDown();
					} catch (InterruptedException e) {
						e.printStackTrace();
					}
				}
				
			};
			executorService.execute(runnable);
		}
		countDownLatch.await();
		System.out.println("submit总共cost 时间:" + (System.currentTimeMillis()-startTime)/1000 + "秒");
		executorService.shutdown();
		return list;
	}

CountDownLatch是一次性的,state减到0后就释放锁,如果再想用就只能重新创建一个,如果希望循环使用,推荐使用CyclicBarrier.

Semaphore

信号量。与CountDownLatch不同的是,同样也是定义了资源总量state=permits,当state>0时就能获得锁,并将state-1,当state=0时只能等待其他线程释放锁,当其他线程释放锁时state+1,这样等待的线程又能获得这个锁

当Semaphore的permits定义为1时,就是互斥锁,当permits>1时就是共享锁

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章