鎖的簡單應用html
用lock來保證原子性(this.count++這段代碼稱爲臨界區)java
什麼是原子性,就是不可分,從頭執行到尾,不能被其餘線程同時執行。數組
可經過CAS來實現原子操做this
CAS(Compare and Swap):spa
CAS操做須要輸入兩個數值,一箇舊值(指望操做前的值)和一個新值,在操做期間先比較下舊值有沒有發生變化,若是沒有發生變化,才交換成新值,發生了變化則不交換。操作系統
CAS主要經過compareAndSwapXXX()方法來實現,而這個方法的實現須要涉及底層的unsafe類.net
unsafe類:java不能直接訪問操做系統底層,而是經過本地方法來訪問。Unsafe類提供了硬件級別的原子操做線程
這裏有個介紹原子操做的博客設計
https://my.oschina.net/xinxingegeya/blog/499223code
還有對unsafe類詳解的博客
http://www.cnblogs.com/mickole/articles/3757278.html
1 public class Counter{ 2 private Lock lock = new Lock(); 3 private int count = 0; 4 public int inc(){ 5 lock.lock(); 6 this.count++; 7 lock.unlock(); 8 return count; 9 } 10 }
不可重入鎖
先來設計一種鎖
1 public class Lock{ 2 private boolean isLocked = false; 3 public synchronized void lock() throws InterruptedException{ 4 while(isLocked){ 5 wait(); 6 } 7 isLocked = true; 8 } 9 public synchronized void unlock(){ 10 isLocked = false; 11 notify(); 12 } 13 }
這實際上是個不可重入鎖,舉個例子
1 public class Count{ 2 Lock lock = new Lock(); 3 public void print(){ 4 lock.lock(); 5 doAdd(); 6 lock.unlock(); 7 } 8 public void doAdd(){ 9 lock.lock(); 10 //do something 11 lock.unlock(); 12 } 13 }
當調用print()方法時,得到了鎖,這時就沒法再調用doAdd()方法,這時必須先釋放鎖才能調用,因此稱這種鎖爲不可重入鎖,也叫自旋鎖。
可重入鎖
設計以下:
1 public class Lock{ 2 boolean isLocked = false; 3 Thread lockedBy = null; 4 int lockedCount = 0; 5 public synchronized void lock() 6 throws InterruptedException{ 7 Thread thread = Thread.currentThread(); 8 while(isLocked && lockedBy != thread){ 9 wait(); 10 } 11 isLocked = true; 12 lockedCount++; 13 lockedBy = thread; 14 } 15 public synchronized void unlock(){ 16 if(Thread.currentThread() == this.lockedBy){ 17 lockedCount--; 18 if(lockedCount == 0){ 19 isLocked = false; 20 notify(); 21 } 22 } 23 } 24 }
相對來講,可重入就意味着:線程能夠進入任何一個它已經擁有的鎖所同步着的代碼塊。
第一個線程執行print()方法,獲得了鎖,使lockedBy等於當前線程,也就是說,執行的這個方法的線程得到了這個鎖,執行add()方法時,一樣要先得到鎖,因不知足while循環的條件,也就是不等待,繼續進行,將此時的lockedCount變量,也就是當前得到鎖的數量加一,當釋放了全部的鎖,才執行notify()。若是在執行這個方法時,有第二個線程想要執行這個方法,由於lockedBy不等於第二個線程,致使這個線程進入了循環,也就是等待,不斷執行wait()方法。只有當第一個線程釋放了全部的鎖,執行了notify()方法,第二個線程才得以跳出循環,繼續執行。
這就是可重入鎖的特色。
java中經常使用的可重入鎖
synchronized
java.util.concurrent.locks.ReentrantLock
ps:順便記錄下java中實現原子操做的類(記錄至http://blog.csdn.net/huzhigenlaohu/article/details/51646455)