Java信號量模型需要我們不斷的進行學習在學習的時候會有不少的問題阻礙著我們下面我們就來看看同步鎖模型只是最簡單的同步模型同一時刻只有一個線程能夠運行同步代碼
有的時候我們希望處理更加復雜的同步模型比如生產者/消費者模型讀寫同步模型等這種情況下同步鎖模型就不夠用了我們需要一個新的模型這就是我們要講述的Java信號量模型
Java信號量模型的工作方式如下線程在運行的過程中可以主動停下來等待某個Java信號量模型的通知這時候該線程就進入到該信號量的待召(Waiting)隊列當中等到通知之後再繼續運行
很多語言裡面同步鎖都由專門的對象表示對象名通常叫Monitor同樣在很多語言中Java信號量模型通常也有專門的對象名來表示比如MutexSemphore
Java信號量模型要比同步鎖模型復雜許多一些系統中信號量甚至可以跨進程進行同步另外一些信號量甚至還有計數功能能夠控制同時運行的線程數
我們沒有必要考慮那麼復雜的模型所有那些復雜的模型都是最基本的模型衍生出來的只要掌握了最基本的信號量模型——等待/通知模型復雜模型也就迎刃而解了
我們還是以Java語言為例Java語言裡面的同步鎖和Java信號量模型概念都非常模糊沒有專門的對象名詞來表示同步鎖和信號量只有兩個同步鎖相關的關鍵字——volatile和synchronized
這種模糊雖然導致概念不清但同時也避免了MonitorMutexSemphore等名詞帶來的種種誤解我們不必執著於名詞之爭可以專注於理解實際的運行原理
在Java語言裡面任何一個Object Reference都可以作為同步鎖同樣的道理任何一個Object Reference也可以作為Java信號量模型
Object對象的wait()方法就是等待通知Object對象的notify()方法就是發出通知
具體調用方法為
()等待某個Java信號量模型的通知
public static final Object signal = new Object();
… f() {
synchronized(singal) { // 首先我們要獲取這個信號量這個信號量同時也是一個同步鎖
// 只有成功獲取了signal這個信號量兼同步鎖之後我們才可能進入這段代碼
signalwait(); // 這裡要放棄信號量本線程要進入signal信號量的待召(Waiting)隊列
// 可憐辛辛苦苦爭取到手的Java信號量模型就這麼被放棄了
// 等到通知之後從待召(Waiting)隊列轉到就緒(Ready)隊列裡面
// 轉到了就緒隊列中離CPU核心近了一步就有機會繼續執行下面的代碼了
// 仍然需要把signal同步鎖競爭到手才能夠真正繼續執行下面的代碼命苦啊
需要注意的是上述代碼中的signalwait()的意思signalwait()很容易導致誤解signalwait()的意思並不是說signal開始wait而是說運行這段代碼的當前線程開始wait這個signal對象即進入signal對象的待召(Waiting)隊列
()發出某個Java信號量模型的通知
… f() {
synchronized(singal) { // 首先我們同樣要獲取這個信號量同時也是一個同步鎖
// 只有成功獲取了signal這個信號量兼同步鎖之後我們才可能進入這段代碼
signalnotify(); // 這裡我們通知signal的待召隊列中的某個線程
// 如果某個線程等到了這個通知那個線程就會轉到就緒隊列中
// 但是本線程仍然繼續擁有signal這個同步鎖本線程仍然繼續執行
// 嘿嘿雖然本線程好心通知其他線程
// 但是本線程可沒有那麼高風亮節放棄到手的同步鎖
// 本線程繼續執行下面的代碼
需要注意的是signalnotify()的意思signalnotify()並不是通知signal這個對象本身而是通知正在等待signal信號量的其他線程
以上就是Object的wait()和notify()的基本用法
實際上wait()還可以定義等待時間當線程在某Java信號量模型的待召隊列中等到足夠長的時間就會等無可等無需再等自己就從待召隊列轉移到就緒隊列中了
另外還有一個notifyAll()方法表示通知待召隊列裡面的所有線程這些細節問題並不對大局產生影響
From:http://tw.wingwit.com/Article/program/Java/hx/201311/11145.html