3、讀寫鎖ReentrantReadWriteLock,適用於"讀多寫少"的多線程應用場景,"讀-寫"互斥,"寫-寫"互斥,而讀-讀可以共享同讀鎖,即一個線程獲取讀鎖,其它線程可直接進入讀,不會被阻塞。
(1) 相關接口
創建讀寫鎖對象
- ReentrantReadWriteLock rwLock = new ReentrantReadWriteLock();
獲取讀鎖
- Lock readLock = rwLock.readLock();
獲取寫鎖
- Lock writeLock = rwLock.writeLock();
(2).讀寫鎖使用基本結構
- //對所有的讀操作添加讀鎖
- readLock.lock();
- try{
- //code to read
- }finally{
- readLock.unlock();
- }
- //對所有的寫操作添加寫鎖
- writeLock.lock();
- try{
- //code to write
- }finally{
- writeLock.unlock();
- }
(3) 測試代碼:
- import Java.util.concurrent.locks.Lock;
- import Java.util.concurrent.locks.ReentrantReadWriteLock;
- class Reader extends Thread {
- private Lock readLock = null;
- public Reader(Lock readLock) {
- this.readLock = readLock;
- }
- public void run() {
- while (true) {
- readLock.lock();
- try {
- System.out.println(Thread.currentThread().getName()
- + ":read action for 1 seconds-"+ReadWriteLock.testVal);
- } finally {
- readLock.unlock();
- }
- try {
- Thread.sleep(1000);
- } catch (InterruptedException e) {
- e.printStackTrace();
- }
- }
- }
- }
- class Writer extends Thread {
- private Lock writeLock = null;
- public Writer(Lock writeLock) {
- this.writeLock = writeLock;
- }
- public void run() {
- while (true) {
- writeLock.lock();
- try {
- System.out.println(Thread.currentThread().getName()
- + ":write action for 2 seconds");
- if(ReadWriteLock.testVal.equals("1111"))
- ReadWriteLock.testVal = "2222";
- else
- ReadWriteLock.testVal = "1111";
- } finally {
- writeLock.unlock();
- }
- try {
- Thread.sleep(2000);
- } catch (InterruptedException e) {
- e.printStackTrace();
- }
- }
- }
- }
- public class ReadWriteLock {
- public static String testVal = "Initiation";
- public static void main(String[] args) {
- ReentrantReadWriteLock lock = new ReentrantReadWriteLock();
- Lock readLock = lock.readLock();
- Lock writeLock = lock.writeLock();
- Reader reader1 = new Reader(readLock);
- reader1.setName("reader1");
- Reader reader2 = new Reader(readLock);
- reader2.setName("reader2");
- Reader reader3 = new Reader(readLock);
- reader3.setName("reader3");
- Reader reader4 = new Reader(readLock);
- reader4.setName("reader4");
- Writer writer = new Writer(writeLock);
- writer.setName("writer1");
- reader1.start();
- reader2.start();
- reader3.start();
- reader4.start();
- writer.start();
- }
- }
輸出:
reader1:read action for 1 seconds-Initiation reader3:read action for 1 seconds-Initiation writer1:write action for 2 seconds reader2:read action for 1 seconds-1111 reader4:read action for 1 seconds-1111 reader3:read action for 1 seconds-1111 reader1:read action for 1 seconds-1111 reader4:read action for 1 seconds-1111 reader2:read action for 1 seconds-1111 writer1:write action for 2 seconds reader4:read action for 1 seconds-2222 reader1:read action for 1 seconds-2222 reader3:read action for 1 seconds-2222 reader2:read action for 1 seconds-2222
4、總結
Lock接口替代synchronized
Lock接口可以比sychronized提供更廣泛的鎖定操作,可以提供多把不同的鎖,且鎖之間互不干涉。
Lock接口提供lock()與unlock()方法,使用明確調用來完成同步的,OO思想好於前者。
Lock可以自由操控同步范圍(scope)。
Lock接口支持nested lock(嵌套鎖定),並提供了豐富的api。
Lock接口提供了tryLock()方法,支持嘗試取得某個object lock。