1. 程式人生 > >5、CountDownLatch原始碼分析

5、CountDownLatch原始碼分析

首先看下下面這段程式碼:

package com.mmall.concurrency.example.atomic;

import com.mmall.concurrency.annoations.ThreadSafe;
import lombok.extern.slf4j.Slf4j;

import java.util.concurrent.CountDownLatch;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Semaphore;
import java.util.concurrent.atomic.AtomicLong;

@Slf4j
@ThreadSafe
public class AtomicExample2 {

	// 請求總數
	public static int clientTotal = 5000;

	// 同時併發執行的執行緒數
	public static int threadTotal = 200;

	public static AtomicLong count = new AtomicLong(0);

	public static void main(String[] args) throws Exception {
		ExecutorService executorService = Executors.newCachedThreadPool();
		final Semaphore semaphore = new Semaphore(threadTotal);
		final CountDownLatch countDownLatch = new CountDownLatch(clientTotal);
		for (int i = 0; i < clientTotal; i++) {
			executorService.execute(() -> {
				try {
					semaphore.acquire();
					add();
					semaphore.release();
				} catch (Exception e) {
				}
				countDownLatch.countDown();
			});
		}
		countDownLatch.await();
		executorService.shutdown();
		System.out.println("count:{}" + count.get());
	}

	private static void add() {
		count.incrementAndGet();
		// count.getAndIncrement();
	}
}

1、程式碼中使用了final CountDownLatch countDownLatch = new CountDownLatch(clientTotal);來初始化CountDownLatch物件 2、通過檢視CountDownLatch的該構造方法:主要是對CountDownLatch類中的變數sync進行了初始化的賦值。 在這裡插入圖片描述 3、在使用CountDownLatch的時候,使用的是countDownLatch.countDown();方法,而countDown方法的原始碼如下: 在這裡插入圖片描述 其releaseShared方法明顯是要將sync變數進行減1的操作,但是為了保證原子性,底層原始碼使用瞭如下:首先這裡使用的是一個死迴圈(也就是為什麼說耗效能的原因),迴圈中不斷獲取head的值,而最終break的條件是h==head。所以看其中邏輯,裡面的compareAndSetWaitStatus,這裡就是很有名的CAS的全稱了 在這裡插入圖片描述

此時再看看CountDownLatch的概念: CountDownLatch是一個同步工具類,用來協調多個執行緒之間的同步,或者說起到執行緒之間的通訊(而不是用作互斥的作用)。 CountDownLatch能夠使一個執行緒在等待另外一些執行緒完成各自工作之後,再繼續執行。使用一個計數器進行實現。計數器初始值為執行緒的數量。當每一個執行緒完成自己任務後,計數器的值就會減一。當計數器的值為0時,表示所有的執行緒都已經完成了任務,然後在CountDownLatch上等待的執行緒就可以恢復執行任務。