我们先看一个典型的Dictionary 的一段代码 ,
package com.concurreny.aqs;
import java.util.Map;
import java.util.TreeMap;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantReadWriteLock;
import java.util.concurrent.locks.ReentrantReadWriteLock.ReadLock;
import java.util.concurrent.locks.ReentrantReadWriteLock.WriteLock;
import javax.xml.crypto.Data;
//读写锁ReentrantReadWriteLock:读读共享,读写互斥,写写互斥!
public class ReentrantWriteReadLockTest {
ReentrantReadWriteLock lock = new ReentrantReadWriteLock();
ReadLock readLock = lock.readLock();
WriteLock writeLock = lock.writeLock();
public void read(){
try {
readLock.lock();
System.out.println("线程"+Thread.currentThread().getName()+"进入。。。");
Thread.sleep(3000);
System.out.println("线程"+Thread.currentThread().getName()+"退出。。。");
} catch (InterruptedException e) {
e.printStackTrace();
}finally{
readLock.unlock();
}
}
public void write(){
try {
writeLock.lock();
System.out.println("线程"+Thread.currentThread().getName()+"进入。。。");
Thread.sleep(3000);
System.out.println("线程"+Thread.currentThread().getName()+"退出。。。");
} catch (InterruptedException e) {
e.printStackTrace();
}finally{
writeLock.unlock();
}
}
public static void main(String[] args) {
final ReentrantWriteReadLockTest wr = new ReentrantWriteReadLockTest();
Thread t1 = new Thread(new Runnable() {
public void run() {
wr.read();
}
}, "t1");
Thread t2 = new Thread(new Runnable() {
public void run() {
wr.read();
}
}, "t2");
Thread t3 = new Thread(new Runnable() {
public void run() {
wr.write();
}
}, "t3");
Thread t4 = new Thread(new Runnable() {
public void run() {
wr.write();
}
}, "t4");
t1.start();
t2.start();
//t3.start();
//t4.start();
}
}
class RWDictionary {
private final Map<String, Data> m = new TreeMap<String, Data>();
private final ReentrantReadWriteLock rwl = new ReentrantReadWriteLock();
private final Lock r = rwl.readLock();
private final Lock w = rwl.writeLock();
public Data get(String key) {
r.lock();
try { return m.get(key); }
finally { r.unlock(); }
}
public String[] allKeys() {
r.lock();
try { return (String[]) m.keySet().toArray(); }
finally { r.unlock(); }
}
public Data put(String key, Data value) {
w.lock();
try { return m.put(key, value); }
finally { w.unlock(); }
}
public void clear() {
w.lock();
try { m.clear(); }
finally { w.unlock(); }
}
}
- Read lock has no condition object
- Does not support to upgrade lock
r.lock()
w.lock();
try{
} finally{
w.unlock()
}
try{
}finally{
r.unlock()
}
- support to downgrade lock
w.lock()
r.lock();
try{
} finally{
r.unlock()
}
try{
}finally{
w.unlock()
}
Case 分享
-
下面看这个例子t1 写锁, t2 是读锁, t1获得了锁
此时线程owner 是t1, state 0_1 值为1
-
此时t2 前来尝试获得读锁
image.png - t2 拿不到锁,进行排队
-
在来t3 是读锁,t4 是写锁, t3 ,t4 排队
image.png - t1 释放写锁
此时t2 获得了锁,但是不是exclusive 的的, state 现在为0
- 在t1 release 时候,unpark t2, ,t2 里从park状态激活,state =1_0
同时 t2 进入到doAcquireShared 线程 循环 运行setHeadAndPropagate,
private void setHeadAndPropagate(Node node, int propagate) {
Node h = head; // Record old head for check below
setHead(node);
if (propagate > 0 || h == null || h.waitStatus < 0 ||
(h = head) == null || h.waitStatus < 0) {
Node s = node.next;
if (s == null || s.isShared())
doReleaseShared();
}
}
再进入doReleaseShared, 在此时释放t2. t2 节点从队列去除。 t3 线程被unpark, t3 节点成为头结点。 当它进入doAcquireShared->setHeadAndPropagate 进入不了doReleaseShared, 因为t4 不是shared 的,所以t4 线程不能被激活。在此时state 为2_0
image.png
网友评论