7.2 重入鎖(ReentrantLock)
阿新 • • 發佈:2019-01-22
鎖(Lock)通過應用重入鎖(ReentrantLock)的類,它將使用的是重入的互斥鎖。這個鎖連線著一個持有計數。當一個執行緒持有鎖,和請求鎖通過執行lock()、lockUninterruptibly()或其中一個tryLock()方法時,持有計數就會加1。當執行緒執行unlock()的方法時,這個持有計數就會減1.當計數為0時,鎖就會釋放。
重入鎖(ReentrantLock)提供相同的併發和記憶體語義作為內部的監測器鎖去呼叫同步方法和阻塞。然而,它的擴充套件性和提供更好的應用在多個執行緒高競爭的情況(執行緒會頻繁請求一個鎖,這個鎖已經被其它執行緒作用,也就是與其它執行緒競爭)。當許多執行緒試圖去獲取一個共享資源時,JVM就會花更少的時間去安排這些執行緒,反而用更多的時間去執行。
他們使用重入鎖(ReentrantLock)的lock()和unlock()的方法去包含和釋放一個重入鎖(ReentrantLock)。當呼叫執行緒請求lock()的方法後,其它執行緒想使用鎖就沒有效果,直到鎖被釋放了執行緒才會有效。
執行上面的程式碼,出現的結果如下:
重入鎖(ReentrantLock)提供相同的併發和記憶體語義作為內部的監測器鎖去呼叫同步方法和阻塞。然而,它的擴充套件性和提供更好的應用在多個執行緒高競爭的情況(執行緒會頻繁請求一個鎖,這個鎖已經被其它執行緒作用,也就是與其它執行緒競爭)。當許多執行緒試圖去獲取一個共享資源時,JVM就會花更少的時間去安排這些執行緒,反而用更多的時間去執行。
你可以使用下面的構造方法去初始化一個ReentrantLock的例項:
- ReentranLock():建立一個重入鎖(ReentrantLock)的例項。這個構造器的作用類似於ReentrantLock(false)。
- ReentrantLock(boolean fair):建立一個ReentrantLock例項,帶有特殊的公平策略。輸入true或false,這個鎖需要使用一個公平的策略:在競爭的情況下,這個鎖需要獲取更長的等待執行緒。
重入鎖(ReentrantLock)使用鎖的方法。然而,當請求的執行緒沒有持有鎖,那麼方法unlock()將會丟擲java.lang.IllegaMonitorStateException。當然,重入鎖(Reentrantlock)也提供自己的方法。例如,booleanisFair()返回公平策略,boolean isHeldByCurrentThread()方法在當前執行緒持有鎖會返回true。例子7-1使用了重入鎖(ReentrantLock).
Listing 7-1 在重入鎖的專案中達到同步。
Listing 7-1描述了一個應用,主執行緒建立一對工作執行緒,模擬工作和離開關鍵部分。package com.owen.thread.chapter7; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; import java.util.concurrent.TimeUnit; import java.util.concurrent.locks.ReentrantLock; public class RLDemo { public static void main(String[] args) { ExecutorService executor = Executors.newFixedThreadPool(2); final ReentrantLock lock = new ReentrantLock(); class Worker implements Runnable { private final String name; Worker(String name) { this.name = name; } @Override public void run() { lock.lock(); try { if (lock.isHeldByCurrentThread()) System.out.printf( "Thread %s entered critical section.%n", name); System.out.printf("Thread %s performing work.%n", name); try { Thread.sleep(2000); } catch (InterruptedException ie) { ie.printStackTrace(); } System.out.printf("Thread %s finished working.%n", name); } finally { lock.unlock(); } } } executor.execute(new Worker("ThdA")); executor.execute(new Worker("ThdB")); try { executor.awaitTermination(5, TimeUnit.SECONDS); } catch (InterruptedException ie) { ie.printStackTrace(); } executor.shutdownNow(); } }
他們使用重入鎖(ReentrantLock)的lock()和unlock()的方法去包含和釋放一個重入鎖(ReentrantLock)。當呼叫執行緒請求lock()的方法後,其它執行緒想使用鎖就沒有效果,直到鎖被釋放了執行緒才會有效。
執行上面的程式碼,出現的結果如下:
Thread ThdA entered critical section.
Thread ThdA performing work.
Thread ThdA finished working.
Thread ThdB entered critical section.
Thread ThdB performing work.
Thread ThdB finished working.