前言
调试JDBC反序列化的时候,里面有这种操作,有点好奇就来看看1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28public static ConnectionUrl getConnectionUrlInstance(String connString, Properties info) {
if (connString == null) {
throw ExceptionFactory.createException(WrongArgumentException.class, Messages.getString("ConnectionString.0"));
}
String connStringCacheKey = buildConnectionStringCacheKey(connString, info);
ConnectionUrl connectionUrl;
rwLock.readLock().lock();
connectionUrl = connectionUrlCache.get(connStringCacheKey);
if (connectionUrl == null) {
rwLock.readLock().unlock();
rwLock.writeLock().lock();
try {
// Check again, in the meantime it could have been cached by another thread.
connectionUrl = connectionUrlCache.get(connStringCacheKey);
if (connectionUrl == null) {
ConnectionUrlParser connStrParser = ConnectionUrlParser.parseConnectionString(connString);
connectionUrl = Type.getConnectionUrlInstance(connStrParser, info);
connectionUrlCache.put(connStringCacheKey, connectionUrl);
}
rwLock.readLock().lock();
} finally {
rwLock.writeLock().unlock();
}
}
rwLock.readLock().unlock();
return connectionUrl;
}
demo
1 | package org.example; |
1 | package org.example; |
输出结果1
2
3
4
5
6
7
8
9
10
11
12----Thread:Thread-0----read first value:0.0
----Thread:Thread-3----read first value:0.0
----Thread:Thread-4----read first value:0.0
----Thread:Thread-2----read first value:0.0
----Thread:Thread-1----read first value:0.0
----Thread:Thread-4----read second value:0.0
----Thread:Thread-1----read second value:0.0
----Thread:Thread-0----read second value:0.0
----Thread:Thread-2----read second value:0.0
----Thread:Thread-3----read second value:0.0
----Thread:Thread-5----write first value:0.38882443875894124
----Thread:Thread-6----write first value:0.537279172993168
可以看到,在read second value
这一段结束了,才开始write的操作,也就是说在没有释放readlock
的时候,writelock
是锁着的,也就是 读读不互斥,写写不互斥,读写有互斥
如果把锁注释,也就是下面的代码1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33package org.example;
import java.util.concurrent.locks.ReentrantLock;
import java.util.concurrent.locks.ReentrantReadWriteLock;
public class ReadWriteLockTest {
private double data = 0;
ReentrantReadWriteLock rwl = new ReentrantReadWriteLock();
private ReentrantLock lock = new ReentrantLock();
public void get(){
try {
System.out.println("----Thread:"+Thread.currentThread().getName()+"----read first value:"+data);
Thread.sleep(1000);
System.out.println("----Thread:"+Thread.currentThread().getName()+"----read second value:"+data);
} catch (Exception e) {
// TODO: handle exception
}
}
public void put(){
try {
data = Math.random();
System.out.println("----Thread:"+Thread.currentThread().getName()+"----write first value:"+data);
Thread.sleep(100);
} catch (Exception e) {
// TODO: handle exception
}
}
}
结果如下1
2
3
4
5
6
7
8
9
10
11
12----Thread:Thread-2----read first value:0.0
----Thread:Thread-3----read first value:0.0
----Thread:Thread-0----read first value:0.0
----Thread:Thread-1----read first value:0.0
----Thread:Thread-4----read first value:0.0
----Thread:Thread-5----write first value:0.7311360215541859
----Thread:Thread-6----write first value:0.32755079667745735
----Thread:Thread-0----read second value:0.32755079667745735
----Thread:Thread-1----read second value:0.32755079667745735
----Thread:Thread-3----read second value:0.32755079667745735
----Thread:Thread-2----read second value:0.32755079667745735
----Thread:Thread-4----read second value:0.32755079667745735
可以看到write写到中间了
getConnectionUrlInstance
回到开头的代码,可以发现这里是在读取缓存的时候加锁,读完了就释放,然后在加上写锁,往缓存列表放入URL