java 併發

併發
(By wind5shy:http://blog.csdn.net/wind5shy)

Thread
n       start():初始化線程,使線程開始執行,Java虛擬機調用該線程的run()。

n       yield():線程暫停,回到可執行狀態,鎖保留,讓出CPU時間,但只讓給同優先級的線程,所以如果某線程使用yield()後如果沒有相同優先級的線程則該線程又會再次被執行。

n       sleep():線程暫停,回到可執行狀態,鎖保留,讓出CPU時間,可使不同優先級的線程獲得執行的機會。

n       join():等待該線程執行完畢。

n       setPriority():設置線程優先級。JDK有10個優先級,但操作系統的優先級各不相同,所以無法做到完美的映射,可行的策略是隻使用MIN_PRIORITY、NORM_PRIORITY和MAX_PRIORITY三個優先級。

n       setDaemon():將該線程標記爲守護線程或用戶線程(後臺線程),當正在運行的線程都是守護線程時,Java 虛擬機退出(即程序立即結束,如書上的例子)。後臺線程創建的任何線程都會自動被設置爲後臺線程。

n       interrupt():中斷線程。

n       interrupted():測試當前線程是否已經中斷並清除線程的中斷標識。換句話說,如果連續兩次調用該方法,則第二次調用必定返回 false。異常捕獲時也將清除線程的中斷標識,所以異常被捕獲時這個標識總是爲false。

n       isInterrupted():測試線程是否已經中斷,線程的中斷狀態不受該方法的影響。

n       run():繼承Thread或實現Runnable的一般目的就是改寫run(),將要併發執行的代碼需要寫在裏面。如果在子類中新建其他方法,如run1(),寫在裏面的代碼是不能併發執行的。

synchronized關鍵字
被synchronized修飾的代碼爲同步代碼,只有獲得對象鎖(又稱監視器)的線程才能訪問這些代碼,直到訪問完成釋放鎖其他線程才能訪問,但類中非synchronized的代碼其他線程什麼時候都可以訪問。synchronized static鎖的是class對象,所以相當於給整個類上鎖。synchronized關鍵字不是方法簽名(private、static是)的一部分,所以在繼承和重載的時候還是要同步的話需要手動加上。

一個例子:

synchronized f();

synchronized g();

h();

如果某線程正在執行f(),則其他線程不能執行同一對象的g(),但可以執行h()。

原子操作
對除long和double以外的基本類型進行簡單的賦值或返回值操作是原子操作,long和double加上valitale關鍵字後相應操作也是原子操作。但如果把這些操作寫在方法裏方法就不是該方法就不一定是原子操作了,比如int i = 1;這單個語句是原子操作沒有問題(否則多線程下面的同步就沒法控制了)但void setI { int i = 1;}就很可能不是原子操作了。

臨界區/同步塊:synchronized(object){//some code},線程在進入some code(臨界區)之前必須獲得object的鎖(而不是包含這段代碼的對象的鎖)

Object的線程控制
n       wait():暫停線程並釋放當前對象的鎖。 T將其自身放置在對象的等待集中,然後放棄此對象上的所有同步要求。在發生以下四種情況之一前,T被禁用,且處於休眠狀態:

1.  其他某個線程調用此對象的notify(),並且線T被任選爲被喚醒的線程。

2.  其他某個線程調用此對象的notifyAll()。

3.  其他某個線程中斷T。

4.  大約已經到達指定的實際時間。但是,如果timeout爲零,則不考慮實際時間,在獲得通知前T將一直等待。

然後,從對象的等待集中刪除線程T,重新進行線程調度。然後,該線程以常規方式與其他線程競爭,以獲得在該對象上同步的權利;一旦獲得對該對象的控制權,該對象上的所有其同步聲明都將被恢復到以前的狀態,這就是調用wait()時的情況。然後,T從wait()的調用中返回。所以,從wait()返回時,該對象和T的同步狀態與調用wait()時的情況完全相同。

n       notify()/notifyAll():喚醒當前對象監視器(對象鎖)上等待的單個/所有線程。(如果所有線程都在當前對象上等待,則會選擇喚醒其中一個線程。)選擇是任意性的,並在對實現做出決定時發生。線程通過調用其中一個wait(),在對象的監視器上等待。 直到當前線程放棄此對象上的鎖定,才能繼續執行被喚醒的線程。被喚醒的線程將以常規方式與在當前對象上主動同步的其他所有線程進行競爭;例如,喚醒的線程在作爲鎖定當前對象的下一個線程方面沒有可靠的特權或劣勢。(這是Sun JDK1.6 API中的解釋,所以書中說線程在notify()之後就進入就緒狀態是不完全正確。當然,實際情況中很可能只有notify()後的線程在等待對象鎖,就可以馬上獲得鎖而進入就緒狀態。可以參考下面的線程狀態圖。)

上面三個方法都只能作爲擁有當前對象的鎖的線程來調用,即只能在同步方法或同步塊裏使用。

線程狀態圖:

n       lock pool:等待鎖定池(我個人的叫法,正規的叫法不太清楚),包含被notify()喚醒的線程及其他等待鎖定對象線程;在當前線程執行完釋放對象鎖之後,這些線程通過競爭選取一個線程獲得對象鎖。

n       sleep pool:休眠池(個人的叫法,Sun JDK1.6 API叫做對象的等待集),包含正在休眠的線程。

死鎖
必須同時滿足的四個條件:

1、  互斥:有資源不能被共享。

2、  佔有與請求:進程佔有資源同時等待其他進程佔有的資源。

3、  不剝奪:進程佔有的資源不能被強行剝奪。

4、  循環等待:若干進程之間形成一種頭尾相接的循環等待資源關係。

所以解除死鎖只需打破其中一個條件即可。

(By wind5shy:http://blog.csdn.net/wind5shy)

本文來自CSDN博客,轉載請標明出處:http://blog.csdn.net/wind5shy/archive/2010/03/04/5346490.aspx

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章