今天要介紹 java.util.concurrent.locks package 下面 ReentrantLock 的類別,它是屬於 Lock 的一種實作,其實 ReentrantLock 相似於前面幾天所提到的 Synchronized。它們之間主要的差別在於 ReentrantLock 有 Lock 和 Unlock 開發程式的人要自已的控制鎖, Synchronized 會自動的幫我們控制鎖。
ReentrantLock 類別主要提供了 lock()、unlock()、newCondition()、tryLock()…等等的方法,今天主要是介紹使用 lock 和 unlock 方法。
lock 方法主要是要把保護的變數鎖圯來,然後 unlock 方法主要是把鎖打開來,讓其它的執行緒去取得共享變數的存取。
以下吏用 ReentrantLock 類別,來保護 ArrayList 非執行緒安全的 Collection,使得多執行在同時 add 資料時不會有掉資料的問題,Sample code 如下:
import java.util.List;
import java.util.concurrent.locks.Lock;
public class LockThreadExample implements Runnable {
private Lock lock;
private List<String> list;
public LockThreadExample(Lock lock, List<String> list) {
this.lock = lock;
this.list = list;
}
@Override
public void run() {
try {
this.lock.lock();
for (int i = 1; i <= 10; i++) {
Thread.sleep(1000L);
this.list.add("value-" + i);
}
} catch(Exception e) {
throw new RuntimeException(e);
} finally {
this.lock.unlock();
}
}
}
以上是執行緒的程式,建構子主要會接收主程式傳入進來的 list 變數和 ReentrantLock 的 Lock 變數,當在執行 run 方法的時侯會先啟動 lock 鎖起來不讓其它的執行緒進來,等待執完畢之後才會把鎖 unlock 打開來。在這裡會放在 finally 區塊呼叫的原因主要是,預防當程式執行到一半如何出現 Exception 時,也要能夠 unlock 不然程式有可能就會發現問題。就類似我們在使用開檔或是建立 JDBC Connection 時關閉連線也會放在 finally 區塊裡。
以下是主程式的寫法:
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
public class Test {
public static void main(String args[]) throws Exception {
Lock lock = new ReentrantLock();
List<String> list = new ArrayList<String>();
LockThreadExample a = new LockThreadExample(lock, list);
Thread thread1 = new Thread(a);
Thread thread2 = new Thread(a);
Thread thread3 = new Thread(a);
thread1.start();
thread2.start();
thread3.start();
thread1.join();
thread2.join();
thread3.join();
System.out.println(list.size());
}
}
在主程式裡主要會建立 ArrayList 和 ReentrantLock 的物件,並且會啟動 3 個執行緒,以下是執行的結果:
30
從結果可以看到是預期的結果 3 個執行緒,每個執行緒執行 10 次迴圈 3*10=30,因此 ReentrantLock 可以保諏非執行安全的物件。
明天還會繼續介紹 ReentrantLock 的 newCondition() 的用法。
『其實 ReentrantLock 相似於前面幾天所提到的 Synchronized。它們之間主要的差別在於 ReentrantLock 有 Lock 和 Unlock 開發程式的人要自已的控制鎖, Synchronized 會自動的幫我們控制鎖。』
其實主要差別不止如此。
歷史因素, ReentrantLock
是效率較高的。
Lock granuality 不同。請見良葛格的文章: https://www.ithome.com.tw/voice/106958
我再去研究看看, 謝謝啦!