ReadWriteLock
1. Read/write the top interface of the Lock. 2Copy the code
ReentrantReadWriteLock
ReadWriteLock implementation class member variable: ReentrantReadWriteLock. ReadLock readerLock (read lock) ReentrantReadWriteLock. WriteLock writerLock (write) the Sync Sync (synchronizer) Both read and write locks implement Lock interfacesCopy the code
The sample code
private ReadWriteLock lock = new ReentrantReadWriteLock();
public void method(a) {
lock.readLock().lock();
//lock.writeLock().lock();
try {
Thread.sleep(1000);
System.out.println("hello");
} catch (Exception e) {
e.printStackTrace();
} finally {
lock.readLock().unlock();
//lock.writeLock().unlock();}}Copy the code
ReentrantReadWriteLock constructor
// fair indicates whether the lock is fair. The default value is unfair
public ReentrantReadWriteLock(boolean fair) {
// Create a synchronizer
sync = fair ? new FairSync() : new NonfairSync();
// Pass the current object into the read/write lock, mainly using its synchronizer
readerLock = new ReadLock(this);
writerLock = new WriteLock(this);
}
Copy the code
ReadLock.lock()
public void lock(a) {
// Because the read lock is shared, the synchronizer's acquireShared method is called
sync.acquireShared(1);
}
public final void acquireShared(int arg) {
// The structure of the acquire method is familiar
if (tryAcquireShared(arg) < 0)
// Failed to obtain the lock and entered the waiting queue
doAcquireShared(arg);
}
protected final int tryAcquireShared(int unused) {
/* * Walkthrough: * 1. If write lock held by another thread, fail. * 2. Otherwise, this thread is eligible for * lock wrt state, so ask if it should block * because of queue policy. If not, try * to grant by CASing state and updating count. * Note that step does not check for reentrant * acquires, which is postponed to full version * to avoid having to check hold count in * the more typical non-reentrant case. * 3. If step 2 fails either because thread * apparently not eligible or CAS fails or count * saturated, chain to version with full retry loop. */
// Get the current thread
Thread current = Thread.currentThread();
// Get the value of state
int c = getState();
//exclusiveCount specifies the number of exclusive locks (write locks)
// If the write lock exists and the exclusive thread is not the current thread, return -1
if(exclusiveCount (c) ! =0&& getExclusiveOwnerThread() ! = current)return -1;
// Get the number of read locks
int r = sharedCount(c);
// The readerShouldBlock method is used to determine whether the lock is eligible for a lock
// r < MAX_COUNT indicates the maximum number of locks
CompareAndSetState Indicates whether the CAS operation is successful
if(! readerShouldBlock() && r < MAX_COUNT && 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 1;
}
return fullTryAcquireShared(current);
}
Copy the code
writeLock.lock()
public void lock(a) {
sync.acquire(1);
}
public final void acquire(int arg) {
if(! tryAcquire(arg) && acquireQueued(addWaiter(Node.EXCLUSIVE), arg)) selfInterrupt(); }protected final boolean tryAcquire(int acquires) {
/* * Walkthrough: * 1. If read count nonzero or write count nonzero * and owner is a different thread, fail. * 2. If count would saturate, fail. (This can only * happen if count is already nonzero.) * 3. Otherwise, this thread is eligible for lock if * it is either a reentrant acquire or * queue policy allows it. If so, update state * and set owner. */
Thread current = Thread.currentThread();
int c = getState();
int w = exclusiveCount(c);
// if c is not 0, some thread holds the lock.
// Write lock feature, this lock thread unless its own thread, reentrant
if(c ! =0) {
// (Note: if c ! = 0 and w == 0 then shared count ! = 0)
// Must be the current thread
if (w == 0|| current ! = getExclusiveOwnerThread())return false;
if (w + exclusiveCount(acquires) > MAX_COUNT)
throw new Error("Maximum lock count exceeded");
// Reentrant acquire
setState(c + acquires);
return true;
}
// Check whether there is a lock condition
// 1. WriterShouldBlock fair and unfair different processing, if the lock is fair to determine whether there is no thread in the wait queue
//2. Check whether the CAS operation is successful
if(writerShouldBlock() || ! compareAndSetState(c, c + acquires))return false;
// Succeeded in setting the exclusive thread to acquire the lock
setExclusiveOwnerThread(current);
return true;
}
Copy the code