ReentrantReadWriteLock读写锁
ReentrantReadWriteLock是一把可重入读写锁,提高了读的性能。读写锁时如何实现了呢。
其实读写锁还是通过一个compareAndSet实现的,只是里面的state的含义不一样了,原先是表示线程的重入次数,现在对该变量做了拆分。高16位表示读线程的重入次数,第16位表示写线程的重入次数。
下面我们看几个变量和方法
static final int SHARED_SHIFT = 16;
//1 0000 0000 0000 0000 用于读线程重入一次
static final int SHARED_UNIT = (1 << SHARED_SHIFT);
//读线程最大重入次数
static final int MAX_COUNT = (1 << SHARED_SHIFT) - 1;
//FFFF FFFF FFFF FFFF 用于计算写线程重入次数
static final int EXCLUSIVE_MASK = (1 << SHARED_SHIFT) - 1;
//获取读线程重入次数
static int sharedCount(int c) { return c >>> SHARED_SHIFT; }
//获取写线程重入次数
static int exclusiveCount(int c) { return c & EXCLUSIVE_MASK; }
获取写锁
final boolean tryWriteLock() {
Thread current = Thread.currentThread();
int c = getState();
//如果c等于0,说明空闲,如果非0,说明已经被占用了
if (c != 0) {
//获取写线程重入次数
int w = exclusiveCount(c);
//如果当前没有写线程,或者写线程不是当前线程,直接返回失败
if (w == 0 || current != getExclusiveOwnerThread())
return false;
//如果写线程已经超过最大重入次数了,则报错
if (w == MAX_COUNT)
throw new Error("Maximum lock count exceeded");
}
//占用锁
if (!compareAndSetState(c, c + 1))
return false;
setExclusiveOwnerThread(current);
return true;
}
获取读锁
final boolean tryReadLock() {
Thread current = Thread.currentThread();
for (;;) {
int c = getState();
//如果当前存在写锁,并且不是当前线程,则直接获取锁失败
if (exclusiveCount(c) != 0 &&
getExclusiveOwnerThread() != current)
return false;
//获取读锁重入次数
int r = sharedCount(c);
if (r == MAX_COUNT)
throw new Error("Maximum lock count exceeded");
//读锁占用
if (compareAndSetState(c, c + SHARED_UNIT)) {
if (r == 0) {
firstReader = current;
firstReaderHoldCount = 1;
} else if (firstReader == current) {
firstReaderHoldCount++;
} else {
HoldCounter rh = cachedHoldCounter;
if (rh == null || rh.tid != getThreadId(current))
cachedHoldCounter = rh = readHolds.get();
else if (rh.count == 0)
readHolds.set(rh);
rh.count++;
}
return true;
}
}
}
还没有评论,来说两句吧...