cyclicbarrier簡介
cyclicbarrier也是基於reentrantlock和condition的乙個同步工具類,它的作用是讓一些執行緒到達某個公共屏障點時,等待未到達的執行緒。當所有執行緒到達屏障點時,繼續往下執行。
先看乙個例子
public
class
cyclicbarrierdemo
implements
runnable
@override
public
void
run(
)catch
(exception e)
}public
static
void
main
(string[
] args)
throws ioexception
system.in.
read()
;}}
實現原理
和其他同步工具不同的是,它的內部並沒有繼承aqs的內部類sync。
private
static
class
generation
//同步操作鎖
private
final reentrantlock lock =
newreentrantlock()
;//執行緒***
private
final condition trip = lock.
newcondition()
;// 等待的執行緒數
private
final
int parties;
// 所有執行緒到達後執行的任務
private
final runnable barriercommand;
// 屏障代
private generation generation =
newgeneration()
;// 還能阻塞的執行緒數
private
int count;
public
cyclicbarrier
(int parties, runnable barrieraction)
# await
cyclicbarrier最重要的方法就是await了,它的作用在例子中已經體會到了,下面進入**看看它到底是如何實現的。
private
intdowait
(boolean timed,
long nanos)
throws interruptedexception, brokenbarrierexception,timeoutexception
// 前面都是條件判斷,等待的執行緒數減1
int index =
--count;
if(index ==0)
finally
}for(;
;)catch
(interruptedexception ie)
else}if
(g.broken)
//如果執行緒因為破壞屏障操作而被喚醒則丟擲異常
throw
newbrokenbarrierexception()
;if(g != generation)
//如果執行緒因為換代操作而被喚醒則返回計數器的值
return index;
if(timed && nanos <=
0l)}
}finally
}
邏輯較長總結一下:
如果當前執行緒不是最後乙個執行緒,也就是說count不為0時,根據呼叫的await是否為限時等待,呼叫condition的await方法,此時執行緒釋放鎖,進入condition的等待佇列(aqs那篇文章中講過),當它被喚醒時需要判斷當前屏障是否被破壞,並且判斷屏障是否換代。
總結一下什麼時候會破壞屏障:
a. 某乙個執行緒被中斷
b. 屏障任務執行失敗
c. 屏障換代
d. 等待時間設定小於0
e. 呼叫reset方法重置
什麼時候會換代:
a. 當所有執行緒都到達屏障,並且任務成功執行
b. 呼叫reset方法
2. 如果當前執行緒是最後乙個到達屏障的執行緒,那麼先執行任務,然後對屏障換代,執行nextgeneration方法。
private
void
nextgeneration()
private
void
breakbarrier()
至此cyclicbarrier已經講述完畢,最後一點cyclicbarrier可以復用,即當屏障使用完一次之後,自動的重置執行緒數。但是countdownlach則不會重置計數器。 Java併發程式設計系列 CountDownLatch
countdownlatch簡介 countdownlatch是基於aqs實現的乙個執行緒同步工具,也稱為閉鎖。它的作用是讓乙個或者多個執行緒等待某個事件的發生。簡單的理解為countdownlatch有乙個正數計數器,countdown方法對計數器做減操作,await方法等待計數器達到0。所有aw...
Java的高併發程式設計系列(三)
鎖定某物件o,如果o的屬性發生改變,不影響鎖的使用,但是如果o變成另外乙個物件,則鎖定的物件發生改變,應該避免將鎖定物件的引用變成另外乙個物件。public class demo17 catch interruptedexception e system.out.println thread.cur...
JAVA併發程式設計
通過常量字串 string 來呼叫 wait 或 notify 方法所導致的問題是,jvm 編譯器會在內部自動將內容相同的 string 轉變為相同的物件。這意味著,即便你建立了兩個不同的 mywaitnotify 例項,他們內部的 mymonitorobject 變數也會指向相同的 string ...