1. 程式人生 > >關於CyclicBarrier的執行順序

關於CyclicBarrier的執行順序

ren left p s 說明 star oop event @override open

  • 認識CyclicBarrier, 先看兩個文檔介紹

CyclicBarrier(int parties, Runnable barrierAction)

Creates a new CyclicBarrier that will trip when the given number of parties (threads) are waiting upon it, and which will execute the given barrier action when the barrier is tripped, performed by the last thread entering the barrier.

int

await()

Waits until all parties have invoked await on this barrier.
  • 舉例,示例代碼

    

技術分享
 1 public class Main {
 2 
 3     private static CyclicBarrier barrier ;
 4 
 5     public Main(){
 6 
 7     }
 8 
 9     static class Worker implements Runnable{
10         int id;
11 
12         public
Worker(int i){ 13 id = i; 14 } 15 16 @Override 17 public void run() { 18 System.out.println("thread is working : "+id); 19 20 try { 21 barrier.await(); 22 } catch (InterruptedException e) { 23 e.printStackTrace();
24 } catch (BrokenBarrierException e) { 25 e.printStackTrace(); 26 } 27 28 System.out.println("thread is ending : "+id); 29 } 30 } 31 32 public static void main(String[] args) { 33 34 barrier = new CyclicBarrier(2, new Runnable() { 35 @Override 36 public void run() { 37 try { 38 Thread.sleep(3000); 39 } catch (InterruptedException e) { 40 e.printStackTrace(); 41 } 42 System.out.println("Master is finished......."); 43 } 44 }); 45 46 for (int i=0;i<2;i++){ 47 Worker worker = new Worker(i); 48 new Thread(worker).start(); 49 } 50 51 } 52 }
示例代碼

  • 問題:parties滿足全部進入await後,barrierAction與await的喚醒,誰先誰後?
  • 實驗結果: 示例代碼執行結果

thread is working : 0
thread is working : 1
Master is finished.......
thread is ending : 1
thread is ending : 0

    結果說明:CyclicBarrier中,當各參與方(parties)到達之後,構造函數中的barrier action會先執行,之後各線程的await才會再返回。

  • JDK源代碼佐證:

    

技術分享
 1  private int dowait(boolean timed, long nanos)
 2         throws InterruptedException, BrokenBarrierException,
 3                TimeoutException {
 4         final ReentrantLock lock = this.lock;
 5         lock.lock();
 6         try {
 7             final Generation g = generation;
 8 
 9             if (g.broken)
10                 throw new BrokenBarrierException();
11 
12             if (Thread.interrupted()) {
13                 breakBarrier();
14                 throw new InterruptedException();
15             }
16 
17             int index = --count;
18             if (index == 0) {  // tripped
19                 boolean ranAction = false;
20                 try {
21                     final Runnable command = barrierCommand;
22                     if (command != null)
23                         command.run();
24                     ranAction = true;
25                     nextGeneration();
26                     return 0;
27                 } finally {
28                     if (!ranAction)
29                         breakBarrier();
30                 }
31             }
32 
33             // loop until tripped, broken, interrupted, or timed out
34             for (;;) {
35                 try {
36                     if (!timed)
37                         trip.await();
38                     else if (nanos > 0L)
39                         nanos = trip.awaitNanos(nanos);
40                 } catch (InterruptedException ie) {
41                     if (g == generation && ! g.broken) {
42                         breakBarrier();
43                         throw ie;
44                     } else {
45                         // We‘re about to finish waiting even if we had not
46                         // been interrupted, so this interrupt is deemed to
47                         // "belong" to subsequent execution.
48                         Thread.currentThread().interrupt();
49                     }
50                 }
51 
52                 if (g.broken)
53                     throw new BrokenBarrierException();
54 
55                 if (g != generation)
56                     return index;
57 
58                 if (timed && nanos <= 0L) {
59                     breakBarrier();
60                     throw new TimeoutException();
61                 }
62             }
63         } finally {
64             lock.unlock();
65         }
66     }
JDK CyclicBarrier源代碼

  從代碼可以看出,barrierCommand執行(21行)之後,才在finally裏調用breakeBarrier(29行),從而喚醒其他線程。證明示例代碼的運行結論。

關於CyclicBarrier的執行順序