一、釋放鎖
1.void unlock()方法
- 嘗試釋放鎖,如果當前線程持有鎖,則調用該方法會讓該線程對該線程持有的AQS狀態值減1,如果減去1後當前狀態值爲0,則當前線程會釋放該鎖,否則僅僅減去1而已,如果當前線程沒有持有該鎖而調用了該方法就會拋出IllegalMonitorStateException異常,代碼如下
public void unlock() {
sync.release();
}
public final boolean tryRelease( int releases) {
int c = getState() - releases;
if(Thread.currentThread() != getExclusiveOwnerThread()) {
throw new IllegalMonitorStateException();
}
boolean free = false;
if(c == 0) {
free = true;
setExclusiveOwnerThread(null);
}
setState(c);
return free;
}
- 如上述代碼,如果當前線程不是該鎖的持有者則直接拋出異常,否則查看狀態值是否爲0,爲0則說明當前線程要放棄對該鎖的持有權,則執行代碼把當前鎖的持有者設置爲null,如果狀態值不爲0,則僅僅讓當前線程對該鎖的可重入次數減1.
2.下面以一個案例作爲講解
package com.ruigege.LockSourceAnalysis6;
import java.util.ArrayList;
public static class ReentrantLockList {
private ArrayList<String> array = new ArrayList<String>();
private volatile ReentrantLock lock = new ReentrantLock();
public void add(String e) {
lock.lock();
try {
array.add(e);
}finally {
lcok.unlock();
}
}
public void remove(String e) {
lock.lock();
try {
array.remove(e);
}finally {
lock.unlock();
}
}
public String get(int index) {
lock.lock();
try {
return array.get(index);
}finally {
lock.unlock();
}
}
}
- 上述代碼實現了一個線程不安全的array,當一個線程獲取到鎖的時候,進行一系列的增刪改查,如果有其他線程想要獲取到該鎖,那麼就會被放到AQS的隊列中,等待第一個線程釋放鎖,來供它們獲取。
二、讀寫鎖ReentrantReadWriteLock的原理
- 解決線程安全問題只需要ReentrantLock即可,但是大多數情況下,該鎖是獨佔鎖,某時只有一個線程可以獲取到該鎖,那麼實際上大多情況是寫少讀多,顯然這個場景是無法滿足的。所以ReentrantReadWriteLock就應運而生了,ReentrantReadWriteLock採用的時讀寫分離的策略,可以允許多個線程同時獲取鎖。
三、源碼:
- 所在包:com.ruigege.ConcurrentListSouceCodeAnalysis5
https://github.com/ruigege66/ConcurrentJava
- 歡迎關注微信公衆號:傅里葉變換,個人賬號,僅用於技術交流