判斷線程中是否有安全隱患?
1,先明確線程的代碼有哪些
2,線程代碼中是否有共享數據
3,是否有多條語句操作共享數據
解決方法:
同步解決
同步函數:synchronized 作爲修飾詞加在函數上。
持的鎖是:this
同步函數和同步代碼塊的區別?
同步函數比同步代碼塊簡單。
同步函數不用刻意定義鎖對象,減少了代碼的縮進
同步函數用的鎖是固定的:就是this。
同步代碼塊鎖是任意的。
相對而言,同步代碼塊用的多一些。而且鎖是指定的,閱讀性好一些。
靜態同步函數的鎖是什麼呢?
該類的所屬字節碼文件對象:類名.Class
類名.class :是一個屬性,表示該類所屬的字節碼文件對象。
懶漢式被多線程併發訪問時:
會出現線程安全問題,因爲:
1,多個線程共享一個對象。
2,有多條語句操作共享數據。
懶漢式中減少鎖的判斷次數:
多一層判段。
面試:懶漢式,併發訪問?,提高效率?。
class SingleDemo{
private static SingleDemo sg;
private SingleDemo(){}
public static SingleDemo getInstance(){
if(sg!=null){
synchronized(SingleDemo.class) {
if(sg!=null){
sg = newSingleDemo();
}
}
}
return sg;
}
}
線程間通信:
多個線程處理同一個資源,但是處理的動作卻一樣。
常用的機制是等待喚醒機制。
wait():將運行的線程置於凍結狀態,釋放了執行權和執行資格,並將等待的線程存儲
到了線程池。
notify():
對線程池中的等待線程進行喚醒,讓線程恢復到運行狀態,
或者恢復到臨時阻塞狀態。其實就是讓等待的線程再次具備執行資格。
注意:一次只喚醒一個,而且隨機的。
notifyAll():
喚醒線程池中所有的等待線程。
wait notifynotifyAll方法都用在同步中。
必須標示出是作用在哪個同步的鎖上。
用法:鎖.wait 鎖.notify 鎖.notifyAll();
java.util.concurrent.locks
Lock接口
在jdk1.5中提供了Lock對象。
lock();獲取鎖
unlock();釋放鎖
newCondition():獲取與鎖相結合的Condition對象。
Condition:
await
signal
signalAll
在jdk1.5中提供了Lock對象替代了synchronized
Lock接口中提供了獲取鎖lock(),釋放鎖unlock();
同步使用的隱士的獲取鎖和釋放鎖動作。
而升級後,將獲取鎖和釋放鎖變成顯示的。
以前同步中用於操作鎖的方法 wait notify notifyAll,
也被jdk1.5中的對象替代了,替代對象是Condition,將操作的鎖的方法單獨從Object中封裝到了Condition對象中。
早期同步中的鎖用的Object中的操作方waitnotify notifyAll。
升級後。
同步鎖被Lock替代變成了指定鎖。Object中方法也被Condition封裝替代,替代方法是Condition對象的中awaitsignal signalAll。
那麼升級後,在對鎖操作,就必須讓Lock和Condition相結合.
如何將Lock和Condition結合呢?
可以通過Lock接口中的newCondition()來獲取和該鎖對象相結合的Condition操作的鎖的方法
新升級的內容Lock Condition的好處:
一個Lock可以綁定多個 用於操作鎖的方法對象。 Lock上可以有多個Condition。這樣就解決了
多生產者和多消費者以前用notifyAll喚醒全部,導致本方被喚醒效率低的問題。
給生產者分配一個Condition,給消費者分配另一個Condition。
可以實現,生產者中喚醒消費者,而不在喚醒本方
停止線程:
如何停止:結束run方法,即結束循環,結束循環一般是判斷或修改標記。
當線程中存在凍結線程的語句時,讀不到修改標記的語句。需要用到interrupt來強制中斷線程的凍結狀態。
interrupt:
強制中斷線程的凍結狀態,讓線程變成運行或臨時阻塞狀態。不拋出interruptedExceptio異常。
setDaemon(Boolean):
將線程設置爲守護線程,需要在開啓線程之前設置;
守護線程可以簡單理解爲後臺線程;
當前臺線程都結束時,後臺線程自動結束;
當線程都變成守護線程時,進程結束。
join:
當執行線程(A)執行到某一個線程(B)時,該線程(A)會釋放執行權和執行資格處於凍結狀態。
此時某一個線程(B)會被執行,而執行線程(A)必須等到某一個線程(B)執行完畢後,該執行線程纔可以被執行。
何時用join方法:
當在執行過程中,需要臨時加入一個線程進行運算,可以使用join方法。
toString:
Thread.currentThread().toString()
返回當前線程的名字、優先級、所屬的線程組。
setPrivority:
設置線程優先級。1—10;數值越大優先級越高。
MAX_PRIORITY 10
MIN_PRIORITY 1
NORM_PRIORITY 5
yield():
暫停當前線程並執行其他線程。