首页 > 基础资料 博客日记
java基础----AQS---ReentrantLock
2023-07-27 18:01:23基础资料围观282次
ReentrantLock Demo:
private Integer value = 0; //计数器初始值
public void testReentrantLock() {
ReentrantLock lock = new ReentrantLock();
for (int i=0;i<10;i++) {
threadPoolExecutor.submit(() -> {
try {
lock.lock();
value = value +1; //顺序+1
System.out.println("threadName:"+Thread.currentThread().getName() + ":value="+value);
}catch (Exception ex) {
ex.printStackTrace();
}finally {
lock.unlock();
}
});
}
}
输出结果:
threadName:pool-1-thread-1:value=1
threadName:pool-1-thread-3:value=2
threadName:pool-1-thread-2:value=3
threadName:pool-1-thread-4:value=4
threadName:pool-1-thread-5:value=5
threadName:pool-1-thread-6:value=6
threadName:pool-1-thread-7:value=7
threadName:pool-1-thread-8:value=8
threadName:pool-1-thread-9:value=9
threadName:pool-1-thread-10:value=10
对比下,如果不用锁的话:
threadName:pool-1-thread-2:value=2
threadName:pool-1-thread-1:value=2
threadName:pool-1-thread-3:value=3
threadName:pool-1-thread-4:value=4
threadName:pool-1-thread-5:value=5
threadName:pool-1-thread-6:value=6
threadName:pool-1-thread-7:value=7
threadName:pool-1-thread-8:value=8
threadName:pool-1-thread-9:value=9
threadName:pool-1-thread-10:value=10
获取锁过程:如果尝试获取到的话,直接返回,如果获取不到,进入等待队列,在队列中阻塞循环去获取锁。
/**
* Acquires in exclusive mode, ignoring interrupts. Implemented
* by invoking at least once {@link #tryAcquire},
* returning on success. Otherwise the thread is queued, possibly
* repeatedly blocking and unblocking, invoking {@link
* #tryAcquire} until success. This method can be used
* to implement method {@link Lock#lock}.
*
* @param arg the acquire argument. This value is conveyed to
* {@link #tryAcquire} but is otherwise uninterpreted and
* can represent anything you like.
*/
public final void acquire(int arg) {
if (!tryAcquire(arg) &&
acquireQueued(addWaiter(Node.EXCLUSIVE), arg)) //添加的节点类型是互斥的模式的节点,在释放的时候
selfInterrupt();
}
/**
* Acquires in exclusive uninterruptible mode for thread already in
* queue. Used by condition wait methods as well as acquire.
*
* @param node the node
* @param arg the acquire argument
* @return {@code true} if interrupted while waiting
*/
final boolean acquireQueued(final Node node, int arg) {
boolean failed = true;
try {
boolean interrupted = false;
for (;;) {
final Node p = node.predecessor();
if (p == head && tryAcquire(arg)) {
setHead(node);//区别于共享模式的获取锁,这里不会传播
p.next = null; // help GC
failed = false;
return interrupted;
}
if (shouldParkAfterFailedAcquire(p, node) &&
parkAndCheckInterrupt())
interrupted = true;
}
} finally {
if (failed)
cancelAcquire(node);
}
}
释放锁过程:尝试获释放锁,state是0标示可以释放锁,那就进入下面,从队列尾部向前找到第一个不是空也没有被canced的节点作为next被unpark的节点。被unpark以后这个节点的线程又回到acquireQueued里面的for循环中继续获取锁,若取得锁则设置自己为头节点。后面在等待的节点在循环中如果发现它前面的节点变为头节点则再去尝试获取锁。
/**
* Releases in exclusive mode. Implemented by unblocking one or
* more threads if {@link #tryRelease} returns true.
* This method can be used to implement method {@link Lock#unlock}.
*
* @param arg the release argument. This value is conveyed to
* {@link #tryRelease} but is otherwise uninterpreted and
* can represent anything you like.
* @return the value returned from {@link #tryRelease}
*/
public final boolean release(int arg) {
if (tryRelease(arg)) {
Node h = head;
if (h != null && h.waitStatus != 0)
unparkSuccessor(h);
return true;
}
return false;
}
/**
* Wakes up node's successor, if one exists.
*
* @param node the node
*/
private void unparkSuccessor(Node node) {
/*
* If status is negative (i.e., possibly needing signal) try
* to clear in anticipation of signalling. It is OK if this
* fails or if status is changed by waiting thread.
*/
int ws = node.waitStatus;
if (ws < 0)
compareAndSetWaitStatus(node, ws, 0);
/*
* Thread to unpark is held in successor, which is normally
* just the next node. But if cancelled or apparently null,
* traverse backwards from tail to find the actual
* non-cancelled successor.
*/
Node s = node.next;
if (s == null || s.waitStatus > 0) {
s = null;
for (Node t = tail; t != null && t != node; t = t.prev)
if (t.waitStatus <= 0)
s = t;
}
if (s != null)
LockSupport.unpark(s.thread);
}
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:jacktools123@163.com进行投诉反馈,一经查实,立即删除!
标签:
上一篇:Java面向对象
下一篇:java基础----AQS的问题答疑