1.阻塞鎖
多個線程同時調用同一個方法的時候,所有線程都被排隊處理了。讓線程進入阻塞狀態進行等待,當獲得相應的信號(喚醒,時間) 時,才可以進入線程的准備就緒狀態,准備就緒狀態的所有線程,通過競爭,進入運行狀態。
public class Lock{ private boolean isLocked = false; public synchronized void lock() throws InterruptedException{ while(isLocked){
//當其他線程進來,即處於等待阻塞狀態 wait(); } isLocked = true; } public synchronized void unlock(){ isLocked = false; notify(); } }
但是由於被調用的方法越耗時,線程越多的時候,等待的線程等待的時間也就越長,甚至於幾分鍾或者幾十分鍾。對於Web等對反應時間要求很高的系統來說,這是不可行的,因此需要讓其非阻塞,可以在沒有拿到鎖之后馬上返回,告訴客戶稍后重試。
2.非阻塞鎖
多個線程同時調用一個方法的時候,當某一個線程最先獲取到鎖,這時其他線程判斷沒拿到鎖,這時就直接返回,只有當最先獲取到鎖的線程釋放,其他線程才能進來,在它釋放之前其它線程都會獲取失敗。
public class Lock{ private boolean isLocked = false; public synchronized boolean lock() throws InterruptedException{ if(isLocked){
//當沒有拿到鎖,立即返回,線程不阻塞 return false; } isLocked = true;
return true; } public synchronized void unlock(){ isLocked = false; } }
3.自旋鎖和互斥鎖
當一個線程在獲取鎖的時候,如果鎖已經被其它線程獲取,那么該線程將循環等待,然后不斷的判斷鎖是否能夠被成功獲取,直到獲取到鎖才會退出循環。
獲取鎖的線程一直處於活躍狀態,由於一直調用while循環,但是並沒有執行任何有效的任務,使用這種鎖會造成busy-waiting。
互斥鎖也是為了保護共享資源的同步,在任何時刻,最多只能有一個保持者,也就說,在任何時刻最多只能有一個執行單元獲得鎖。但是兩者在調度機制上略有不同。對於互斥鎖,如果資源已經被占用,資源申請者只能進入睡眠狀態。但是自旋鎖不會引起調用者睡眠,如果自旋鎖已經被別的執行單元保持,調用者就一直循環在那里看是否該自旋鎖的保持者已經釋放了鎖。
//自旋鎖
public class Lock{ private boolean isLocked = false; public synchronized void lock() throws InterruptedException{ while(isLocked){ sout("繼續不斷的循環來判斷是否可以拿到鎖"); } isLocked = true; } public synchronized void unlock(){ isLocked = false; } }
//互斥鎖
public class Lock{ private boolean isLocked = false; public synchronized void lock() throws InterruptedException{ while(isLocked){ //當其他線程進來,直接讓其進入等待狀態,只有當最先拿到鎖的資源,才能繼續執行判斷是否拿到鎖 wait(); } isLocked = true; } public synchronized void unlock(){ isLocked = false; notify(); } }