JUC——線程同步鎖(ReentrantLock)
阿新 • • 發佈:2018-04-27
spa his 進入 star zab serial 進行 zed util
ReentrantLock簡介
ReentrantLock是一個可重復的互斥鎖,又被稱為獨占鎖,可重入的意思是:ReentrantLock鎖可以被單個線程多次獲取。但是在同一個時間點只能被一個線程鎖持有
ReentrantLock使用一個FIFO(先進先出)的等待隊裏來管理獲取該鎖所有線程的。
ReentrantLock是一個獨占鎖,在獲取鎖的之後其所有的操作都是線程獨享的,其他的線程在沒有獲取到鎖之前都需要等待。
public class ReentrantLock implements Lock,java.io.Serializable
ReentrantLock之中分為公平鎖與非公平鎖,它們的區別體現在獲取鎖的機制上是否公平以及執行速度上。、
這兩種鎖的啟用也是非常容易控制的,這個類提供的構造方法如下:
- 無參構造(非公平鎖,NonfairSync)
public ReentrantLock() { sync = new NonfairSync(); }
- 有參構造
public ReentrantLock(boolean fair) { sync = fair ? new FairSync() : new NonfairSync(); }
//fair = true,表示公平鎖,FairSync
//fair = false,表示非公平鎖,NonfairSync
ReentrantLock繼承結構
範例:使用ReentrantLock定義一個多線程賣票的處理程序
package so.strong.mall.concurrent; import java.util.concurrent.locks.Lock; import java.util.concurrent.locks.ReentrantLock; class Ticket { private Lock myLock = new ReentrantLock(); //非公平鎖 private int count = 10; //一共10張票 public void sale() { myLock.lock(); //進入到阻塞狀態,一直到unlock執行後解除阻塞try { if (this.count > 0) { System.out.println(Thread.currentThread().getName() + "賣票,ticket=" + this.count--); } } finally { myLock.unlock(); //不管最終結果如何一定要進行解鎖 } } } public class TestDemo { public static void main(String[] args) { final Ticket ticket = new Ticket(); //多線程要共享同一個數據資源 for (int i = 0; i < 6; i++) { new Thread(new Runnable() { @Override public void run() { while (true) { ticket.sale(); //賣票處理 } } }).start(); } } }
Thread-0賣票,ticket=10 Thread-0賣票,ticket=9 Thread-0賣票,ticket=8 Thread-0賣票,ticket=7 Thread-0賣票,ticket=6 Thread-0賣票,ticket=5 Thread-0賣票,ticket=4 Thread-2賣票,ticket=3 Thread-2賣票,ticket=2 Thread-2賣票,ticket=1
當前的代碼要比直接使用synchronized更加容易,而且鎖的處理機制更加的直觀。通過查看源代碼可以發現,使用lock()進行鎖定的時候會考慮兩種情況:
Sync-java.util.concurrent.locks.ReentrantLock
- FairSync-java.util.concurrent.locks.ReentrantLock
- NonFairSync-java.util.concurrent.locks.ReentrantLock
在進行公平鎖處理的時候每當鎖定一個線程對象就會使用“acquire(1)”方法進行表示:
final void lock() { if (compareAndSetState(0, 1)) setExclusiveOwnerThread(Thread.currentThread()); else acquire(1); }
在進行解鎖時會使用一個"sync.release(1)”釋放方法, 1 表示釋放一個:
public void unlock() { sync.release(1); }
JUC——線程同步鎖(ReentrantLock)