標籤:java 多線程編程
安全執行緒問題產生的原因:
- 多個線程在操作共用的資料
- 操作共用資料的線程代碼有多條
當一個線程在執行操作共用資料的多條代碼過程中,其他線程參與了運算。
就會導致安全執行緒問題的產生。
解決思路:
就是將多條操作共用資料的線程代碼封裝起來,當有線程在執行這些代碼的時候,其他線程時不可以參與運算的。
必須要當前線程吧這些代碼都執行完畢後,其他線程才可以參與運算。
同步代碼塊的格式:
synchronized(對象)
{
需要被同步的代碼;
}
同步的好處:
解決了線程的安全問題。
同步的弊端:
相對降低了效率,因為同步外的線程都會判斷同步鎖。
同步的前提:
同步中必須有多個線程並使用同一個鎖。
【線程同步有2中表現形式,同步代碼塊,同步函數】
生產者,消費者。
多生產者,多消費者的問題。
if判斷標記,只有一次,會導致不該啟動並執行線程運行了。出現了資料錯誤的情況。
while判斷標記,解決了線程擷取執行權後,是否要運行!
notify:只能喚醒一個線程,如果本方喚醒了本方,沒有意義。而且while判斷標記+notify會導致死結。
notifyAll解決了本方線程一定會喚醒對方線程的問題。
jdk1.5以後將同步和鎖封裝成了對象。
並將操作鎖的隱式方式定義到了該對象中,
將隱式動作變成了顯示動作。
Lock介面: 出現替代了同步代碼塊或者同步函數。將同步的隱式鎖操作變成現實鎖操作。
同時更為靈活。可以一個鎖上加上多組監視器。
lock():擷取鎖。
unlock():釋放鎖,通常需要定義finally代碼塊中。
Condition介面:出現替代了Object中的wait notify notifyAll方法。
將這些監視器方法單獨進行了封裝,變成Condition監視器對象。
可以任意鎖進行組合。
await();
signal();
signalAll();
等待/喚醒機制。
涉及的方法:
1,wait(): 讓線程處於凍結狀態,被wait的線程會被儲存到線程池中。
2,notify():喚醒線程池中一個線程(任意).
3,notifyAll():喚醒線程池中的所有線程。
這些方法都必須定義在同步中。
因為這些方法是用於操作線程狀態的方法。
必須要明確到底操作的是哪個鎖上的線程。
為什麼操作線程的方法wait notify notifyAll定義在了Object類中?
因為這些方法是監視器的方法。監視器其實就是鎖。
鎖可以是任意的對象,任意的對象調用的方式一定定義在Object類中。
wait 和 sleep 區別?
1,wait可以指定時間也可以不指定。
sleep必須指定時間。
2,在同步中時,對cpu的執行權和鎖的處理不同。
wait:釋放執行權,釋放鎖。
sleep:釋放執行權,不釋放鎖。
百度搜尋一下 線程同步相關知識
java線程鎖