讀寫鎖(Readers-Writer Lock)顧名思義是一把鎖分為兩部分:讀鎖和寫鎖,其中讀鎖允許多個執行緒同時取得,因為讀取操作本身是執行緒安全的,而寫鎖則是互斥鎖,不允許多個執行緒同時取得寫鎖,且寫入操作和讀取操作也是互斥的。總結來說,讀寫鎖的特徵是:讀讀不互斥、讀寫互斥、寫寫互斥。
在Java 語言中,讀寫鎖定是使用ReentrantReadWriteLock 類別來實現的,其中:
#ReentrantReadWriteLock.ReadLock
表示讀鎖,它提供了lock 方法進行加鎖、unlock 方法進行解鎖。
ReentrantReadWriteLock.WriteLock
表示寫鎖,它提供了 lock 方法進行加鎖、unlock 方法進行解鎖。
它的基礎使用如下程式碼所示:
// 创建读写锁 final ReentrantReadWriteLock readWriteLock = new ReentrantReadWriteLock(); // 获得读锁 final ReentrantReadWriteLock.ReadLock readLock = readWriteLock.readLock(); // 获得写锁 final ReentrantReadWriteLock.WriteLock writeLock = readWriteLock.writeLock(); // 读锁使用 readLock.lock(); try { // 业务代码... } finally { readLock.unlock(); } // 写锁使用 writeLock.lock(); try { // 业务代码... } finally { writeLock.unlock(); }
多個執行緒可以同時取得到讀鎖,稱為讀讀不互斥,如下程式碼所示:
// 创建读写锁 final ReentrantReadWriteLock readWriteLock = new ReentrantReadWriteLock(); // 创建读锁 final ReentrantReadWriteLock.ReadLock readLock = readWriteLock.readLock(); Thread t1 = new Thread(() -> { readLock.lock(); try { System.out.println("[t1]得到读锁."); Thread.sleep(3000); } catch (InterruptedException e) { e.printStackTrace(); } finally { System.out.println("[t1]释放读锁."); readLock.unlock(); } }); t1.start(); Thread t2 = new Thread(() -> { readLock.lock(); try { System.out.println("[t2]得到读锁."); Thread.sleep(3000); } catch (InterruptedException e) { e.printStackTrace(); } finally { System.out.println("[t2]释放读锁."); readLock.unlock(); } }); t2.start();
以上程式執行結果如下:
讀取鎖定和寫入鎖定同時使用是互斥的(也就是不能同時獲得),這稱之為讀寫互斥,如下程式碼所示:
// 创建读写锁 final ReentrantReadWriteLock readWriteLock = new ReentrantReadWriteLock(); // 创建读锁 final ReentrantReadWriteLock.ReadLock readLock = readWriteLock.readLock(); // 创建写锁 final ReentrantReadWriteLock.WriteLock writeLock = readWriteLock.writeLock(); // 使用读锁 Thread t1 = new Thread(() -> { readLock.lock(); try { System.out.println("[t1]得到读锁."); Thread.sleep(3000); } catch (InterruptedException e) { e.printStackTrace(); } finally { System.out.println("[t1]释放读锁."); readLock.unlock(); } }); t1.start(); // 使用写锁 Thread t2 = new Thread(() -> { writeLock.lock(); try { System.out.println("[t2]得到写锁."); Thread.sleep(3000); } catch (InterruptedException e) { e.printStackTrace(); } finally { System.out.println("[t2]释放写锁."); writeLock.unlock(); } }); t2.start();
以上程式執行結果如下:
多個執行緒同時使用寫鎖也是互斥的,這稱之為寫寫互斥,如下程式碼所示:
// 创建读写锁 final ReentrantReadWriteLock readWriteLock = new ReentrantReadWriteLock(); // 创建写锁 final ReentrantReadWriteLock.WriteLock writeLock = readWriteLock.writeLock(); Thread t1 = new Thread(() -> { writeLock.lock(); try { System.out.println("[t1]得到写锁."); Thread.sleep(3000); } catch (InterruptedException e) { e.printStackTrace(); } finally { System.out.println("[t1]释放写锁."); writeLock.unlock(); } }); t1.start(); Thread t2 = new Thread(() -> { writeLock.lock(); try { System.out.println("[t2]得到写锁."); Thread.sleep(3000); } catch (InterruptedException e) { e.printStackTrace(); } finally { System.out.println("[t2]释放写锁."); writeLock.unlock(); } }); t2.start();
以上程式執行結果如下:
提升了程式執行效能:多個讀鎖可以同時執行,相較於普通鎖在任何情況下都要排隊執行來說,讀寫鎖提高了程式的執行效能。
避免讀到臨時資料:讀取鎖定和寫入鎖定是互斥排隊執行的,這樣可以保證了讀取操作不會讀到寫了一半的臨時數據。
讀寫鎖定適合多讀少寫的業務場景,此時讀寫鎖定的優點最大。
以上是Java讀寫鎖的用法及其優點是什麼?的詳細內容。更多資訊請關注PHP中文網其他相關文章!