ReentrantReadWriteLock
先寫一段原始代碼
public class Demo3 {
//共享變量
static int count = 0;
public static void readMethod() {
try {
// 爲了展示出多線程同時操作同一數據會出現問題。如果去掉之後可能會正常計算出數據
Thread.sleep(1);
count++;
} catch (InterruptedException e) {
e.printStackTrace();
} finally {
}
}
public static void main(String[] args) throws InterruptedException {
Thread thread = new Thread(() -> {
for (int i = 0; i < 5000; i++) {
// 當次訪問讀鎖
Demo3.readMethod();
}
});
thread.start();
Thread thread2 = new Thread(() -> {
for (int i = 0; i < 5000; i++) {
// 當次訪問讀鎖
Demo3.readMethod();
}
});
thread2.start();
Thread.sleep(20000);
System.out.println("result:" + count);
}
}
預計得值:result: 10000
實際運行得值:result: 9999(經過多次重試,發現小於等於10000)
我們來給它加上鎖ReentrantReadWriteLock
當次兩個線程都使用 讀鎖
public class Demo2 {
//共享變量
static int count = 0;
// 重入讀寫鎖
static ReentrantReadWriteLock rwl = new ReentrantReadWriteLock();
// 寫鎖
static Lock write = rwl.writeLock();
// 讀鎖
static Lock read = rwl.readLock();
//當前方法使用讀鎖
public static void readMethod() {
read.lock(); //讀鎖
try {
// 爲了展示出多線程同時操作同一數據會出現問題。如果去掉之後可能會正常計算出數據
Thread.sleep(1);
count++;
} catch (InterruptedException e) {
e.printStackTrace();
} finally {
read.unlock(); //釋放讀鎖
}
}
//當前方法使用讀鎖
public static void writeMethod() {
write.lock(); //Other
try {
// 爲了展示出多線程同時操作同一數據會出現問題。如果去掉之後可能會正常計算出數據
Thread.sleep(1);
count++;
} catch (InterruptedException e) {
e.printStackTrace();
} finally {
write.unlock();
}
}
public static void main(String[] args) throws InterruptedException {
Thread thread = new Thread(() -> {
for (int i = 0; i < 5000; i++) {
// 當次訪問讀鎖
Demo2.readMethod();
}
});
thread.start();
Thread thread2 = new Thread(() -> {
for (int i = 0; i < 5000; i++) {
// 當次訪問讀鎖
Demo2.readMethod();
}
});
thread2.start();
Thread.sleep(20000);
System.out.println("result:" + count);
}
}
預計得值:result:-10000
實際得值:result:-9999(小於等於10000,如果等於10000,多重試幾次。)
發現:並沒有加鎖效果,讀鎖是共享的(非互斥)
當次兩個線程都使用 寫鎖(代碼基本沒變,就變更了一下訪問的方法)
public class Demo2 {
//共享變量
static int count = 0;
// 重入讀寫鎖
static ReentrantReadWriteLock rwl = new ReentrantReadWriteLock();
// 寫鎖
static Lock write = rwl.writeLock();
// 讀鎖
static Lock read = rwl.readLock();
//當前方法使用讀鎖
public static void readMethod() {
read.lock(); //讀鎖
try {
// 爲了展示出多線程同時操作同一數據會出現問題。如果去掉之後可能會正常計算出數據
Thread.sleep(1);
count++;
} catch (InterruptedException e) {
e.printStackTrace();
} finally {
read.unlock(); //釋放讀鎖
}
}
//當前方法使用讀鎖
public static void writeMethod() {
write.lock(); //Other
try {
// 爲了展示出多線程同時操作同一數據會出現問題。如果去掉之後可能會正常計算出數據
Thread.sleep(1);
count++;
} catch (InterruptedException e) {
e.printStackTrace();
} finally {
write.unlock();
}
}
public static void main(String[] args) throws InterruptedException {
Thread thread = new Thread(() -> {
for (int i = 0; i < 5000; i++) {
// 當次訪問寫鎖
Demo2.writeMethod();
}
});
thread.start();
Thread thread2 = new Thread(() -> {
for (int i = 0; i < 5000; i++) {
// 當次訪問寫鎖
Demo2.writeMethod();
}
});
thread2.start();
Thread.sleep(20000);
System.out.println("result:" + count);
}
}
預計得值:result:10000
實際得值:result:10000(多次重試都是:10000)
發現:有加鎖效果,寫鎖是非共享的(互斥)
當次兩個線程一個使用 寫鎖,另個一使用讀鎖(代碼基本沒變,就變更了一下訪問的方法)
public class Demo2 {
//共享變量
static int count = 0;
// 重入讀寫鎖
static ReentrantReadWriteLock rwl = new ReentrantReadWriteLock();
// 寫鎖
static Lock write = rwl.writeLock();
// 讀鎖
static Lock read = rwl.readLock();
//當前方法使用讀鎖
public static void readMethod() {
read.lock(); //讀鎖
try {
// 爲了展示出多線程同時操作同一數據會出現問題。如果去掉之後可能會正常計算出數據
Thread.sleep(1);
count++;
} catch (InterruptedException e) {
e.printStackTrace();
} finally {
read.unlock(); //釋放讀鎖
}
}
//當前方法使用讀鎖
public static void writeMethod() {
write.lock(); //Other
try {
// 爲了展示出多線程同時操作同一數據會出現問題。如果去掉之後可能會正常計算出數據
Thread.sleep(1);
count++;
} catch (InterruptedException e) {
e.printStackTrace();
} finally {
write.unlock();
}
}
public static void main(String[] args) throws InterruptedException {
Thread thread = new Thread(() -> {
for (int i = 0; i < 5000; i++) {
// 當次訪問讀鎖
Demo2.readMethod();
}
});
thread.start();
Thread thread2 = new Thread(() -> {
for (int i = 0; i < 5000; i++) {
// 當次訪問寫鎖
Demo2.writeMethod();
}
});
thread2.start();
Thread.sleep(20000);
System.out.println("result:" + count);
}
}
預計得值:result:10000
實際得值:result:10000(多次重試都是:10000)
發現:有加鎖效果,讀鎖和寫鎖 是非共享的(互斥)
總結:
- 讀讀不互斥
- 寫寫互斥
- 讀寫互斥