当前位置:网站首页>"Ask every day" reentrantlock locks and unlocks
"Ask every day" reentrantlock locks and unlocks
2022-07-25 14:53:00 【Senior fishing Engineer】

ReentrantLock 、Sync 、FairSync 、NonfairSync Organization relationship between codes
public class ReentrantLock{
abstract static class Sync extends AbstractQueuedSynchronizer{
//...
}
static final class NonfairSync extends Sync {
//...
}
static final class FairSync extends Sync{
//...
}
}
Lock Six methods are defined in the interface
// Lock
void lock();
// Interruptible locking
void lockInterruptibly() throws InterruptedException;
Condition newCondition();
boolean tryLock();
boolean tryLock(long time, TimeUnit unit) throws InterruptedException;
// Unlock
void unlock();
Lock
ReentrantLock.lock
public void lock() {
sync.lock();
}
// This sync yes ReentrantLock A property in
private final Sync sync;
// because Sync yes abstract Embellished , So here Sync Which subclass is it ?
// Look at the construction method , The default is an unfair lock
public ReentrantLock() {
sync = new NonfairSync();
}
// Of course , Whether the fair lock can be specified
public ReentrantLock(boolean fair) {
sync = fair ? new FairSync() : new NonfairSync();
}
NonfairSync.lock
@Override
final void lock() {
if (compareAndSetState(0, 1)) {
setExclusiveOwnerThread(Thread.currentThread());
} else {
acquire(1);
}
}
// First of all, you see @Override, Then yes, this lock() Namely Sync An abstract method in
abstract void lock();
Let's take a step-by-step look at the implementation
1. CAS Set lock status state Value
/** * If the current status value is equal to the expected value , The synchronization status is automatically set to the given update value . * The operation has {@code volatile} Memory semantics of read and write . * * @param expect Look forward to , That is, the old value you expected * @param update New value * @return {@code true} if successful. return false Indicates that the actual value is not equal to the expected value . */
protected final boolean compareAndSetState(int expect, int update) {
//unsafe The operation of native operation
return unsafe.compareAndSwapInt(this, stateOffset, expect, update);
}
2. If the current thread sets the lock state successfully , It indicates that the current thread has successfully obtained the lock , Then set the current thread as the thread holding the lock
/** * The method is AbstractOwnableSynchronizer Medium * AbstractOwnableSynchronizer yes AbstractQueuedSynchronizer The abstract parent class of , * It maintains a thread reference representing the current independent access * private transient Thread exclusiveOwnerThread; * */
protected final void setExclusiveOwnerThread(Thread thread) {
exclusiveOwnerThread = thread;
}
3. If the current thread is not successfully set state The state of
1. Try to get the lock again , If a locked thread is found during this period, it is the current thread ,state++, That is, it supports reentrant
2. The attempt failed , The current thread is created Node node , And then to 『CAS + Dead cycle 』 To ensure that it is put in the waiting queue , At the same time, set the current node as the tail node ,
After the node enters the synchronization queue , Into a 『 The spin 』 The process of , Every node ( Or each thread ) Are observing introspectively ,
When the conditions are met , Got sync status , You can exit from this spin process , Otherwise, it remains in this spin process ( And block the thread of the node )
/** * The method is AbstractOwnableSynchronizer Medium * The effect is * If ( Attempt to acquire lock failed also Adding the current thread to the blocking queue succeeded ){ * Interrupt the current thread * } */
public final void acquire(int arg) {
if (!tryAcquire(arg) && acquireQueued(addWaiter(Node.EXCLUSIVE), arg))
selfInterrupt(); //Thread.currentThread().interrupt();
}
//3.1、tryAcquire(arg);
/** * This method finally arrived nonfairTryAcquire This method * */
final boolean nonfairTryAcquire(int acquires) {
final Thread current = Thread.currentThread();
// Get the status of the current lock
int c = getState();
// If it's unlocked , That is to say state by 0
if (c == 0) {
//CAS Set the lock status to 1, After setting successfully, set the holding thread of the current lock
if (compareAndSetState(0, acquires)) {
setExclusiveOwnerThread(current);
return true;
}
}
// If it is locked And The thread holding the lock is the current thread
else if (current == getExclusiveOwnerThread()) {
int nextc = c + acquires;
if (nextc < 0) // overflow
throw new Error("Maximum lock count exceeded");
// If it's the current thread , that state Add up , Here we can find ,Reentrant It's reentrant
setState(nextc);
return true;
}
// If it is locked And The thread holding the lock is not the current thread , Go straight back to false, That is, the thread failed to acquire the lock
return false;
}
/** * 3.2、addWaiter(Node mode) * Create and queue nodes for the current thread and given pattern . * @param mode Node.EXCLUSIVE for exclusive( Monopoly ), Node.SHARED for shared( share ) * @return New nodes */
private Node addWaiter(Node mode) {
// Create a new node
Node node = new Node(Thread.currentThread(), mode);
/** * Get tail nodes * AQS There are two member variables in , It is used to represent the head and tail nodes in the waiting queue * private transient volatile Node head; * private transient volatile Node tail; */
Node pred = tail;
if (pred != null) {
// Set the head node of the new node to point to the tail node of the original queue
node.prev = pred;
//CAS Set tail node , Guarantee safety
if (compareAndSetTail(pred, node)) {
// New nodes next The node points to itself
pred.next = node;
return node;
}
}
// The front one CAS May fail , Here, an endless loop is used to ensure the success of setting the tail node
enq(node);
return node;
}
private Node enq(final Node node) {
/** * The synchronizer passes “ Dead cycle ” To ensure the correct addition of nodes , stay “ Dead cycle ” Only through CAS After setting the node as the tail node , The current thread can return... From this method , * otherwise , The current thread is constantly trying to set . It can be seen that ,enq(final Node node) Method to send concurrent requests to add nodes through CAS become “ Serialization ” 了 . */
for (; ; ) {
Node t = tail;
if (t == null) {
// Must initialize
if (compareAndSetHead(new Node()))
tail = head;
} else {
node.prev = t;
if (compareAndSetTail(t, node)) {
t.next = node;
return t;
}
}
}
}
/** * 3.3、acquireQueued(final Node node, int arg) * */
final boolean acquireQueued(final Node node, int arg) {
boolean failed = true;
try {
boolean interrupted = false;
for (; ; ) {
final Node p = node.predecessor(); // Namely node.prev
if (p == head && tryAcquire(arg)) {
// Only node.prev Is the head node , Before you can try to get the lock , It also meets the requirements of the queue FIFO principle
setHead(node);
p.next = null; // help GC
failed = false;
return interrupted;
}
if (shouldParkAfterFailedAcquire(p, node) &&
parkAndCheckInterrupt())
interrupted = true;
}
} finally {
if (failed)
cancelAcquire(node);
}
}
Unlock
ReentrantLock.unlock()
@Override
public void unlock() {
// Each unlock is equivalent to state-=1 , Because of the reentrant feature ,state Will be greater than the 1
sync.release(1);
}
//AbstractQueuedSynchronizer.release
public final boolean release(int arg) {
if (tryRelease(arg)) {
// because ReentrantLock It supports reentry , Here, only the thread holding the lock releases all state,
// That is to say state Down to 0 until ,tryRelease Will return true
Node h = head;
if (h != null && h.waitStatus != 0)
// Wake up the next node
unparkSuccessor(h);
return true;
}
return false;
}
//Sync.tryRelease
/** * state yes volatile A single variable decorated , On the basis of visibility, it has atomicity */
@Override
protected final boolean tryRelease(int releases) {
int c = getState() - releases;
// If the currently unlocked thread is not the lock holding thread , Throw an exception
if (Thread.currentThread() != getExclusiveOwnerThread())
throw new IllegalMonitorStateException();
boolean free = false;// Mark whether the current thread has completely released the lock , That is to say state Reduced to 0
if (c == 0) {
//state by 0, It is the only condition for the current thread to completely release the lock mark
free = true;
// Set the current lock holding thread to null
setExclusiveOwnerThread(null);
}
// Write back state
setState(c);
return free;
}
protected final void setState(int newState) {
state = newState;
}
Be careful :
- Exclusive lock , The thread enters the synchronization queue because it failed to get the synchronization status , When the thread is interrupted later , Threads are not removed from the synchronization queue
边栏推荐
- IP地址分类,判断一个网段是子网超网
- 35 quick format code
- H5页面input输入框弹起数字键盘,需要支持小数点
- [C题目]力扣88. 合并两个有序数组
- MySQL 45讲 | 06 全局锁和表锁 :给表加个字段怎么有这么多阻碍?
- Application practice: Great integrator of the paddy classification model [paddlehub, finetune, prompt]
- 51单片机学习笔记(2)
- LeetCode_ Factorization_ Simple_ 263. Ugly number
- PS making and loading GIF pictures tutorial
- Awk from getting started to digging in (23) awk built-in variables argc, argc -- command line parameter transfer
猜你喜欢

GameFramework制作游戏(二)制作UI界面

51 single chip microcomputer learning notes (1)

Sudo rosdep init error ROS installation problem solution

直播课堂系统05-后台管理系统

37 元素模式(行内元素,块元素,行内块元素)
![[MySQL series] - how much do you know about the index](/img/d7/5045a846580be106e2bf16d7b30581.png)
[MySQL series] - how much do you know about the index

45padding不会撑开盒子的情况

51单片机学习笔记(1)

苹果官网产品打折 买iPhone 13 Pro Max 可省600元

Leetcode-198- house raiding
随机推荐
LeetCode-198-打家劫舍
软件测试 -- 1 软件测试知识大纲梳理
Add the jar package under lib directory to the project in idea
51 single chip microcomputer learning notes (1)
How to make a set of code fit all kinds of screens perfectly?
SSM framework integration, simple case
39 simple version of millet sidebar exercise
物理量与单位符号的书写标准
Writing standard of physical quantities and unit symbols
(原创)自定义一个滚屏的RecyclerView
关于ROS2安装connext RMW的进度条卡在13%问题的解决办法
MySQL sort
kibana操作es
阿里云技术专家邓青琳:云上跨可用区容灾和异地多活最佳实践
Awk from getting started to digging in (20) awk parsing command line parameters
Application practice: Great integrator of the paddy classification model [paddlehub, finetune, prompt]
Educational Codeforces Round 132 (Rated for Div. 2) C,D+AC自动机
Content type corresponding to office file
PS making and loading GIF pictures tutorial
awk从入门到入土(20)awk解析命令行参数