【轉】-java多線程讀寫鎖ReadWriteLock
Java多線程中讀寫鎖ReadWriteLock的使用
該博客轉載自?lavimer?的?Java多線程中讀寫鎖ReadWriteLock的使用
1. 概念
讀寫鎖分為讀鎖和寫鎖,多個讀鎖之間是不需要互斥的(讀操作不會改變數據,如果上了鎖,反而會影響效率),寫鎖和寫鎖之間需要互斥,也就是說,如果只是讀數據,就可以多個線程同時讀,但是如果你要寫數據,就必須互斥,使得同一時刻只有一個線程在操作。
2. 案例
2.1 三線程讀數據,三線程寫數據
package com.tao.leanrn.thread.lock;
import java.util.concurrent.locks.ReadWriteLock;
import java.util.concurrent.locks.ReentrantReadWriteLock;
/**
* @ClassName ReadWrite
* @Descriiption 讀寫鎖
* @Author yanjiantao
* @Date 2019/8/21 10:42
**/
public class ReadWrite {
/**
* 共享數據
*/
private int data = 0;
/**
* 讀寫鎖
*/
private ReadWriteLock lock = new ReentrantReadWriteLock();
public void get() {
// 上讀鎖
lock.readLock().lock();
try {
System.out.println(Thread.currentThread().getName() + "----->讀鎖開始執行...");
Thread.sleep((long)(Math.random() * 10));
System.out.println(Thread.currentThread().getName() + "----->讀鎖得到數據data=" + data);
} catch (InterruptedException e) {
e.printStackTrace();
} finally {
// 釋放鎖
lock.readLock().unlock();
}
}
public void set() {
// 上寫鎖
lock.writeLock().lock();
try {
System.out.println(Thread.currentThread().getName() + "----->寫鎖開始執行...");
Thread.sleep((long)(Math.random() * 10));
data++;
System.out.println(Thread.currentThread().getName() + "----->寫鎖得到數據data=" + data);
} catch (InterruptedException e) {
e.printStackTrace();
} finally {
// 釋放寫鎖
lock.writeLock().unlock();
}
}
}
/**
* 測試類
*/
class Main{
public static void main(String[] args) {
ReadWrite readWrite = new ReadWrite();
// 創建100個讀寫線程
for (int i = 0; i < 100; i++) {
new Thread(() -> {
readWrite.get();
}).start();
new Thread(() -> {
readWrite.set();
}).start();
}
}
}
程序運行結果

2.2 模擬Hibernate緩存
public class HibernateCache {
/* 定義一個Map來模擬緩存 */
private Map<String, Object> cache = new HashMap<String, Object>();
/* 創建一個讀寫鎖 */
private ReadWriteLock rwLock = new ReentrantReadWriteLock();
/**
* 模擬Hibernate緩存
* @param key
* @return
*/
private Object getData(String key) {
/* 上讀鎖 */
rwLock.readLock().lock();
/* 定義從緩存中讀取的對象 */
Object value = null;
try {
/* 從緩存中讀取數據 */
value = cache.get(key);
if (value == null) {
/* 如果緩存中沒有數據,我們就把讀鎖關閉,直接上寫鎖【讓一個線程去數據庫中取數據】 */
rwLock.readLock().unlock();
/* 上寫鎖 */
rwLock.writeLock().lock();
try {
/* 上了寫鎖之后再判斷一次【我們只讓一個線程去數據庫中取值即可,當第二個線程過來的時候,發現value不為空了就去緩存中取值】 */
if (value == null) {
/* 模擬去數據庫中取值 */
value = "hello";
}
} finally {
/* 寫完之后把寫鎖關閉 */
rwLock.writeLock().unlock();
}
/* 緩存中已經有了數據,我們再把已經 關閉的讀鎖打開 */
rwLock.readLock().lock();
}
} finally {
/* 最后把讀鎖也關閉 */
rwLock.readLock().unlock();
}
return value;
}
}

浙公網安備 33010602011771號