一、鎖的原理
Java中每個對象都有一個内置鎖,當程式運作到非靜态的synchronized同步方法上時,自動獲得與正在執行的代碼類的目前執行個體(this執行個體)有關的鎖。獲得一個對象的鎖也稱為擷取鎖、鎖定對象、在對象上鎖定或在對象上同步。
當程式運作到synchronized同步方法或代碼塊時該對象鎖才起作用。一個對象隻有一個鎖。是以一個線程獲得該所,就沒有其他線程獲得,直到第一個線程釋放(或傳回)鎖。這也意味着任何其他線程都不能進入該對象上的synchronized方法或代碼塊,直到該鎖被釋放。釋放鎖是指持鎖線程退出synchronized同步方法或代碼塊。
2、注意事項
1) 隻能同步方法,不能同步變量和類。
2) 每個對象隻有一個鎖,是以應該清楚在哪一個對象上同步。
3) 不必同步類的所有方法,類可以同時擁有同步和非同步方法。
4) 如果向擁有同步和非同步方法,則非同步方法可以被多個線程自由通路不受鎖的限制。
5) 線程睡眠時,它所持的鎖不會釋放。
6) 線程可以獲得多個鎖。比如在一個對象的同步方法裡面調用另一個對象的同步方法,則獲得了兩個對象的同步鎖。
7) 同步損害并發性,應該盡可能縮小同步範圍。同步不但可以同步整個方法,還可以同步方法中一部分代碼塊。
8) 使用同步代碼塊時,應該指出在哪個對象上同步,也就是說要獲得哪個對象的鎖,如
二、如果線程不能獲得鎖會怎麼樣
如果線程試圖進入同步方法,而鎖被其他線程占用,則該線程被阻塞。實際上,線程進入該對象的一種池中,必須在那裡等待,直到其所被釋放。
當考慮堵塞時,一定要注意哪個對象正在被用于鎖定:
1、調用用一個對象中非靜态同步方法的線程将被堵塞。如果是不同對象,則線程之間互不幹擾。
2、調用同一個類中的靜态同步方法的線程将被堵塞,它們都是鎖定在相同的Cass對象上。
3、靜态同步方法和非靜态同步方法将永遠不會彼此堵塞,因為靜态方法鎖定在Class對象上,非靜态方法鎖定在該類的對象上。
4、對于同步代碼塊,要看清楚什麼對象已經用于鎖定(synchronized後面括号的内容)。在同一個對象上進行同步的線程将被堵塞,在不同對象上的線程永遠不會被堵塞。
三、鎖對象
Java5中,提供了鎖對象,利用鎖對象可以實作資源的封鎖,用來控制對競争資源并發通路的控制,這些内容主要集中在java.util.concurrent.locks包下,主要有三個接口Condition、Lock、ReadEWriteLock。
具體看個例子:
LockTest.java

View Code
結果為:

上述例子是普通的鎖,不區分讀寫,在這裡,為了提高性能,讀的地方用讀鎖,寫的地方用寫鎖,提高了執行效率。平時的時候盡量寫讀寫鎖,不用普通鎖。


四、死鎖
死鎖發生的可能性很小,即使看似死鎖的代碼,運作時也不一定産生死鎖,發生死鎖的原因是:當兩個線程被堵塞, 每個線程在等待另一個線程時發生死鎖,一般是兩個對象的鎖互相等待造成的。具體例子:
DeathLockTest.java


這時,産生了死鎖,程式不能繼續運作了,但是如果修改一下,就能避免死鎖。


當神已無能為力,那便是魔渡衆生