文章目录
ReentrantLock
Lock
ReentrantLock implements Lock, java.io.Serializable
Demo
package com.kornzhou.javademo.concurrentprogramming.lock;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
public class ReentrantLockDemo {
private Lock lock = new ReentrantLock();
public static void main(String[] args) {
ReentrantLockDemo demo = new ReentrantLockDemo();
demo.method1();
}
private void method1() {
new Thread(() -> {
System.out.println(Thread.currentThread().getName() + " start");
lock.lock();
method2();
System.out.println(Thread.currentThread().getName() + " end");
lock.unlock();
}, "thread-1").start();
}
private void method2() {
System.out.println(Thread.currentThread().getName() + " start2");
lock.lock();
System.out.println(Thread.currentThread().getName() + " end2");
lock.unlock();
}
}
输出
再次调用mehthod2的lock(),并不会等待,是可重入的。
thread-1 start
thread-1 start2
thread-1 end2
thread-1 end
解析lock()
ReentrantLock#lock
// ReentrantLock初始化默认为非公平锁
public ReentrantLock() {
sync = new NonfairSync();
}
public void lock() {
sync.lock();
}
ReentrantLock.NonfairSync
final void lock() {
if (compareAndSetState(0, 1))
setExclusiveOwnerThread(Thread.currentThread());
else
acquire(1);
}
protected final boolean tryAcquire(int acquires) {
// here
return nonfairTryAcquire(acquires);
}
AQS
public final void acquire(int arg) {
if (!tryAcquire(arg) &&
acquireQueued(addWaiter(Node.EXCLUSIVE), arg))
selfInterrupt();
}
ReentrantLock.Sync
// here 可重入代码
final boolean nonfairTryAcquire(int acquires) {
final Thread current = Thread.currentThread();
int c = getState();
if (c == 0) {
if (compareAndSetState(0, acquires)) {
setExclusiveOwnerThread(current);
return true;
}
}
else if (current == getExclusiveOwnerThread()) {
// here 可重入,nextc在原有线程持有锁情况下+1
int nextc = c + acquires;
if (nextc < 0) // overflow
throw new Error("Maximum lock count exceeded");
setState(nextc);
return true;
}
return false;
}
源码
ReentrantLock.FairSync
protected final boolean tryAcquire(int acquires) {
final Thread current = Thread.currentThread();
int c = getState();
if (c == 0) {
// 与非公平锁对比,只多了hasQueuedPredecessors判断,
// 顾名思义,就是有排队的前置任务,为了公平,返回false
if (!hasQueuedPredecessors() &&
compareAndSetState(0, acquires)) {
setExclusiveOwnerThread(current);
return true;
}
}
else if (current == getExclusiveOwnerThread()) {
int nextc = c + acquires;
if (nextc < 0)
throw new Error("Maximum lock count exceeded");
setState(nextc);
return true;
}
return false;
}
AQS#acquireQueued
tryAcquire失败后,没有获得锁的线程会被放到一个FIFO的队列中去,等待再次竞争同步变量来获得锁。
AQS为没有获得锁的线程封装成AbstractQueuedSynchronizer.Node,再添加导队列中去。
// AQS
public final void acquire(int arg) {
if (!tryAcquire(arg) &&
acquireQueued(addWaiter(Node.EXCLUSIVE), arg))
selfInterrupt();
}
final boolean acquireQueued(final Node node, int arg) {
boolean failed = true;
try {
boolean interrupted = false;
for (;;) {
final Node p = node.predecessor(); // p=prev(为空抛异常)
// head代表的是获得锁的节点,只有它释放了state其他线程才能获得这个变量的所有权
if (p == head && tryAcquire(arg)) {
setHead(node);
p.next = null; // help GC
failed = false;
return interrupted;
}
// tryAcquire失败,挂起线程
if (shouldParkAfterFailedAcquire(p, node) &&
parkAndCheckInterrupt())
interrupted = true;
}
} finally {
if (failed)
cancelAcquire(node);
}
}
private static boolean shouldParkAfterFailedAcquire(Node pred, Node node) {
int ws = pred.waitStatus;
if (ws == Node.SIGNAL)
/*
* This node has already set status asking a release
* to signal it, so it can safely park.
*/
return true;
if (ws > 0) {
/*
* Predecessor was cancelled. Skip over predecessors and
* indicate retry.
*/
do {
node.prev = pred = pred.prev;
} while (pred.waitStatus > 0);
pred.next = node;
} else {
/*
* waitStatus must be 0 or PROPAGATE. Indicate that we
* need a signal, but don't park yet. Caller will need to
* retry to make sure it cannot acquire before parking.
*/
compareAndSetWaitStatus(pred, ws, Node.SIGNAL);
}
return false;
}
private final boolean parkAndCheckInterrupt() {
LockSupport.park(this);
return Thread.interrupted();
}
LockSupport
// LockSupport
public static void park(Object blocker) {
Thread t = Thread.currentThread();
setBlocker(t, blocker);
UNSAFE.park(false, 0L); // native方法-线程挂起
setBlocker(t, null);
}
// Thread.parkBlocker赋值
private static void setBlocker(Thread t, Object arg) {
// Even though volatile, hotspot doesn't need a write barrier here.
UNSAFE.putObject(t, parkBlockerOffset, arg);
// 当前线程t的属性parkBlocker赋值=this[本例是ReentrantLock$NonfairSync]
}
Thread#parkBlocker
// Thread
/**
* The argument supplied to the current call to
* java.util.concurrent.locks.LockSupport.park.
* Set by (private) java.util.concurrent.locks.LockSupport.setBlocker
* Accessed using java.util.concurrent.locks.LockSupport.getBlocker
*/
volatile Object parkBlocker;
AQS#addWaiter(Node.EXCLUSIVE)
创建独占模式的入队Node
/**
* Creates and enqueues node for current thread and given mode.
*
* @param mode Node.EXCLUSIVE for exclusive, Node.SHARED for shared
* @return the new node
*/
private Node addWaiter(Node mode) {
Node node = new Node(Thread.currentThread(), mode);
// Try the fast path of enq; backup to full enq on failure
Node pred = tail;
if (pred != null) {
// 在队列尾部添加新节点node,同时更新其前后的节点指针;
// 并(compareAndSetTail)更新AQS.tail节点为新节点node
node.prev = pred;
if (compareAndSetTail(pred, node)) {
pred.next = node;
return node;
}
}
// node入队,失败则一直循环
enq(node);
return node;
}
enq(node)
/**
* Inserts node into queue, initializing if necessary. See picture above.
* @param node the node to insert
* @return node's predecessor
*/
private Node enq(final Node node) {
for (;;) {
Node t = tail;
// 队列空,初始化一个节点
if (t == null) { // Must initialize
// 初始化head节点 = new Node();
if (compareAndSetHead(new Node()))
// 初始化tail = head
tail = head;
} else {
// 队列非空node入队,cas入队失败则一直循环
node.prev = t;
if (compareAndSetTail(t, node)) {
t.next = node;
return t;
}
}
}
}
AQS.Node
先看下Node,四个状态
/** waitStatus value to indicate thread has cancelled */
static final int CANCELLED = 1;
/** waitStatus value to indicate successor's thread needs unparking */
static final int SIGNAL = -1;
/** waitStatus value to indicate thread is waiting on condition */
static final int CONDITION = -2;
/**
* waitStatus value to indicate the next acquireShared should
* unconditionally propagate
*/
static final int PROPAGATE = -3;
AQS提供了共享锁、独占锁两种模式
/** Marker to indicate a node is waiting in shared mode */
static final Node SHARED = new Node();
/** Marker to indicate a node is waiting in exclusive mode */
static final Node EXCLUSIVE = null;
其它属性
volatile int waitStatus;
volatile Node prev;
volatile Node next;
/**
* The thread that enqueued this node. Initialized on
* construction and nulled out after use.
*/
volatile Thread thread;
/**
* Link to next node waiting on condition, or the special
* value SHARED. Because condition queues are accessed only
* when holding in exclusive mode, we just need a simple
* linked queue to hold nodes while they are waiting on
* conditions. They are then transferred to the queue to
* re-acquire. And because conditions can only be exclusive,
* we save a field by using special value to indicate shared
* mode.
*/
// Node.SHARED/Node.EXCLUSIVE
Node nextWaiter;
final boolean isShared() {
return nextWaiter == SHARED;
}