java線程鎖
- 多個線程在操作共享的數據
- 操作共享數據的線程代碼有多條
當一個線程在執行操作共享數據的多條代碼過程中,其他線程參與了運算。
就會導致線程安全問題的產生。
解決思路:
就是將多條操作共享數據的線程代碼封裝起來,當有線程在執行這些代碼的時候,其他線程時不可以參與運算的。
必須要當前線程吧這些代碼都執行完畢後,其他線程才可以參與運算。
同步代碼塊的格式:
synchronized(對象)
{
需要被同步的代碼;
}
同步的好處:
解決了線程的安全問題。
同步的弊端:
相對降低了效率,因為同步外的線程都會判斷同步鎖。
同步的前提:
同步中必須有多個線程並使用同一個鎖。
【線程同步有2中表現形式,同步代碼塊,同步函數】
生產者,消費者。
多生產者,多消費者的問題。
if判斷標記,只有一次,會導致不該運行的線程運行了。出現了數據錯誤的情況。
while判斷標記,解決了線程獲取執行權後,是否要運行!
notify:只能喚醒一個線程,如果本方喚醒了本方,沒有意義。而且while判斷標記+notify會導致死鎖。
notifyAll解決了本方線程一定會喚醒對方線程的問題。
jdk1.5以後將同步和鎖封裝成了對象。
並將操作鎖的隱式方式定義到了該對象中,
將隱式動作變成了顯示動作。
Lock接口: 出現替代了同步代碼塊或者同步函數。將同步的隱式鎖操作變成現實鎖操作。
同時更為靈活。可以一個鎖上加上多組監視器。
lock():獲取鎖。
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線程鎖