I. Introduction
StampedLock is JUC and contract inside JDK1.8 new version of a lock that provides read and write control three modes, when the call to get a lock function when the series will return to a long-type variable that is called to stamp (stamp), the stamp represents the state of the lock.
We know that "read-write locks allow multiple threads simultaneously read shared variables for reading and writing little scenes." That reading and writing little scenes, the performance even better than StampedLock on read-write lock.
ReadWriteLock supports two modes: one is a read lock, one is a write lock. The StampedLock supports three modes, namely:
write lock, optimistic and pessimistic read lock read
. Among them, write locks, semantic and ReadWriteLock pessimistic read locks to write locks, read lock semantics are very similar, allowing multiple threads simultaneously acquire pessimistic read lock, but allows only one thread acquires a write lock, write lock and pessimistic read lock is mutual - repellent. The difference is: after StampedLock in the pessimistic read lock and write lock lock successful, will return a stamp; then unlocked when the need to pass this stamp.
try get the function lock series, when failure to acquire the lock will return to stamp value of 0. You need to pass to obtain stamp value when the lock is returned when you call to release the lock and the lock method when converting.
The implementation is based on internal StampedLock CLH lock, CLH lock principle: Lock maintains a queue of waiting threads, application lock all the threads and failure are recorded in the queue. A node represents a thread, holds a flag locked, in order to determine whether the current thread releases the lock. When a thread attempts to acquire a lock, the end node from the queue as a prelude to the node, loop determines whether all the previous node has successfully releases the lock.
Its core idea is that, when read in optimism if it does write, it should be to obtain a new value by retrying the way, should not be blocking write operations. This pattern is typical of lock-free programming ideas, and CAS spin thinking the same. This mode of operation determines the next StampedLock reading the thread very much and very few write-threaded scene is very suitable, but also to avoid starvation write happening. And reentrant StampedLock not supported and unsupported Condition,
as shown (below
the reference line in FIG.
):
Second, property
private static final int NCPU = Runtime.getRuntime().availableProcessors();
private static final int SPINS = (NCPU > 1) ? 1 << 6 : 0;
private static final int HEAD_SPINS = (NCPU > 1) ? 1 << 10 : 0;
private static final int MAX_HEAD_SPINS = (NCPU > 1) ? 1 << 16 : 0;
private static final int OVERFLOW_YIELD_RATE = 7;
private static final int LG_READERS = 7;
private static final long RUNIT = 1L;
private static final long WBIT = 1L << LG_READERS;
private static final long RBITS = WBIT - 1L;
private static final long RFULL = RBITS - 1L;
private static final long ABITS = RBITS | WBIT;
private static final long SBITS = ~RBITS;
private static final long ORIGIN = WBIT << 1;
private static final long INTERRUPTED = 1L;
private static final int WAITING = -1;
private static final int CANCELLED = 1;
private static final int RMODE = 0;
private static final int WMODE = 1;
private transient volatile WNode whead;
private transient volatile WNode wtail;
transient ReadLockView readLockView;
transient WriteLockView writeLockView;
transient ReadWriteLockView readWriteLockView;
private transient volatile long state;
private static final sun.misc.Unsafe U;
private static final long STATE;
private static final long WHEAD;
private static final long WTAIL;
private static final long WNEXT;
private static final long WSTATUS;
private static final long WCOWAIT;
private static final long PARKBLOCKER;
static {
try {
U = sun.misc.Unsafe.getUnsafe();
Class<?> k = StampedLock.class;
Class<?> wk = WNode.class;
STATE = U.objectFieldOffset(k.getDeclaredField("state"));
WHEAD = U.objectFieldOffset(k.getDeclaredField("whead"));
WTAIL = U.objectFieldOffset(k.getDeclaredField("wtail"));
WSTATUS = U.objectFieldOffset(wk.getDeclaredField("status"));
WNEXT = U.objectFieldOffset(wk.getDeclaredField("next"));
WCOWAIT = U.objectFieldOffset(wk.getDeclaredField("cowait"));
Class<?> tk = Thread.class;
PARKBLOCKER = U.objectFieldOffset(tk.getDeclaredField("parkBlocker"));
} catch (Exception e) { throw new Error(e); }}复制代码
Third, the constructor
//state被初始化为256,写锁标志位128,读锁位
public StampedLock() { state = ORIGIN;}复制代码
Fourth, inner classes
static final class WNode {
volatile WNode prev;
volatile WNode next;
volatile WNode cowait;
volatile Thread thread;
volatile int status;
final int mode;
WNode(int m, WNode p) { mode = m; prev = p; }
}
final class ReadLockView implements Lock {
public void lock() {
readLock();
}
public void lockInterruptibly() throws InterruptedException {
readLockInterruptibly();
}
public boolean tryLock() {
return tryReadLock() != 0L;
}
public boolean tryLock(long time, TimeUnit unit) throws InterruptedException {
return tryReadLock(time, unit) != 0L;
}
public void unlock() {
unstampedUnlockRead();
}
public Condition newCondition() {
throw new UnsupportedOperationException();
}
}
final class WriteLockView implements Lock {
public void lock() {
writeLock();
}
public void lockInterruptibly() throws InterruptedException {
writeLockInterruptibly();
}
public boolean tryLock() {
return tryWriteLock() != 0L;
}
public boolean tryLock(long time, TimeUnit unit) throws InterruptedException {
return tryWriteLock(time, unit) != 0L;
}
public void unlock() {
unstampedUnlockWrite();
}
public Condition newCondition() {
throw new UnsupportedOperationException();
}
}
final class ReadWriteLockView implements ReadWriteLock {
public Lock readLock() {
return asReadLock();
}
public Lock writeLock() {
return asWriteLock();
}
}复制代码
Fifth, write lock acquisition and release
- Write lock acquisition
public long writeLock() {
long s, next;
return ((((s = state) & ABITS) == 0L && U.compareAndSwapLong(this, STATE, s, next = s + WBIT)) ? next : acquireWrite(false, 0L));
}
public long tryWriteLock() {
long s, next;
return ((((s = state) & ABITS) == 0L &&
U.compareAndSwapLong(this, STATE, s, next = s + WBIT)) ?
next : 0L);
}
public long tryWriteLock(long time, TimeUnit unit)
throws InterruptedException {
long nanos = unit.toNanos(time);
if (!Thread.interrupted()) {
long next, deadline;
if ((next = tryWriteLock()) != 0L)
return next;
if (nanos <= 0L)
return 0L;
if ((deadline = System.nanoTime() + nanos) == 0L)
deadline = 1L;
if ((next = acquireWrite(true, deadline)) != INTERRUPTED)
return next;
}
throw new InterruptedException();
}
private long acquireWrite(boolean interruptible, long deadline) { WNode node = null, p;
for (int spins = -1;;) { 复制代码
Sixth, read lock acquisition and release
Seven optimistic reading obtaining, verification
Eight, lock escalation