任務的協作的基本實現

2022-02-26 08:52:46 字數 1592 閱讀 9253

任務不僅是只有競爭的關係,還有協作。所謂的協作,就是一般意義上的協作,多個任務同時完成同乙個問題的各個部分。所以,現在問題已經不是任務間的干涉,而是任務間的協調。因為在這類問題中,某些部分必須在其他部分被解決前解決,而且,在這些任務中,某些是可以併發執行的。某些甚至是所有任務都結束後進行,就像建房子一樣,總得建完地基後才能開始往上建吧。

所以,任務的協作的關鍵就是任務間的協議。怎樣才能實現這種協議呢?還是使用互斥,也就是鎖。沒錯,你沒有看錯,就是使用鎖來實現協作。為什麼可以呢?明明協作與競爭在字面上來說,應該是相反的啊,但是基本構成是可以一樣的啊。因為鎖能夠確保只有乙個任務可以響應某個訊號,就是可以消除任何可能的競爭,在這樣的基礎上,我們就可以將任務自身掛起,直到某個外部條件發生變化,表示是時候讓這個任務開工了。這樣的實現是由object的wait()和notify()來完成的。

wait()可以使我們等待某個條件發生變化,而改變這個條件超出了當前方法的控制能力。通常,這種條件由另乙個任務來改變。但是,這裡要注意,不能讓你的這個任務陷入忙等待中,就是在測試這個條件時,不斷進行空迴圈。因此,wait()會將這個任務掛起,只有在notify()或notifyall()發生時,即發生了喚醒條件,這個任務就會被喚醒並且去檢查這個條件。在任務的加鎖機制這部分,我們知道,呼叫sleep()和yield()時,鎖並沒有被釋放,但是wait()卻大大不同,它會釋放鎖,這就使得其他synchronized方法可以獲得該鎖。這就是為什麼利用鎖就可以達到熱任務的協作的關鍵,因為wait()方法不僅掛起執行緒,而且釋放鎖,然後等到notify()或notifyall()捕捉住喚醒條件,開始執行下一步。我們在使用wait()時,習慣用法就是用乙個檢查喚醒條件的while迴圈來包圍wait()。這點是非常重要的,為什麼呢?原因有下面幾個方面:

1.我們可能有多個任務出於相同的原因在等待同乙個鎖,而第乙個喚醒任務可能會改變這種狀況,那麼這時我們應該怎麼做呢?就是將這個任務掛起,防止其造成這種現象,因為它只需要執行到它滿足喚醒條件時該做的事情就行,其他的事情不需要現在做,自然會有其他喚醒條件,所以,這個迴圈就能使得當它完成工作時被掛起;

2.在這個任務從其wait()中被喚醒的時刻,有可能會有某個其他的任務已經做出了改變,從而使得這個任務在此時不能執行,或者執行其操作已顯得無關緊要,所以必須時時檢查喚醒條件,在這情況下就應該馬上掛起;

3.可能某些任務出於不同的喚醒條件在等待你的物件上的鎖,這時就要看看喚醒條件是否已經改變,如果改變,就應該掛起釋放鎖,而且,注意,這時應該是使用notifyall()。

當然,只要有認真看完上面的內容的,就會產生乙個疑問,就是notify()和notifyall()有什麼區別?notifyall()正如它後面的all,表示喚醒所有正在等待的任務,這句話是不完整的,真正的意思是,它可以喚醒所有等待呼叫notifyall()的任務所持有的鎖的任務。那麼什麼時候該使用notify(),什麼時候該使用notifyall()呢?一般情況下,使用notify()而不是notifyall()是一種優化,因為不用喚醒所有任務,但是我們必須保證一點,就是我們喚醒的是正確的任務,可是啊,如果有多個任務在等待不同的條件,我們又怎能知道我們喚醒的是正確的任務?因為使用notify()只能喚醒乙個任務!所以如果無法保證我們喚醒的是乙個正確的任務,那麼請選擇notifyall(),就像上面第三條所說的情況,你要喚醒的是喚醒條件不同的各個任務,那麼就一起喚醒吧。

執行緒的基本協作機制

接下來講述執行緒中的基本協作機制 1.生產消費模型 2.同時開始 3.等待結束 4.集合點。首先介紹object類中的wait notify方法 public final void wait throws interruptedexception public final void wait lon...

關於openGl與CUDA協作的具體實現

關於opengl與cuda協作的具體實現 共享緩衝區的使用 乙個在空白opengl螢幕中繪製的例子 先宣告兩個全域性變數 緩衝區物件的id,另乙個用於儲存gl pixel unpack buffer 傳遞給opengl的 資料 gluintbuffer 接下來是cuda對共享緩衝區的 名字 cuda...

jbpm的任務管理實現

乙個流程定義有乙個taskmgmtdefinition 乙個taskmgmtdefinition對應多個actor,同時對應多個task 乙個actor有多個task,可以從taskmgmtdefinition中通過task的名稱直接獲取相應的task 乙個流程例項有乙個taskmgmtinstan...