当前位置:网站首页>Interviewer: have you learned about the underlying implementation of reentrantlock? tell us your opinion
Interviewer: have you learned about the underlying implementation of reentrantlock? tell us your opinion
2022-07-23 13:46:00 【Java Architect in Penghu】
We can see that it is a reentrant lock , Let's take a look at its underlying implementation ~
Constructors
When we use it , It's all first new it , So let's first look at its constructor , It mainly has two :
public ReentrantLock()
{
sync = new NonfairSync();
}
public ReentrantLock(boolean fair)
{
sync = fair ? new FairSync() : new NonfairSync();
}
Literally , The difference between them is fair, Fair means fair , You can guess that it is used to build fair locks and unfair locks , Before moving on to the source code , First, let's introduce these two kinds of locks .
Fair lock & Not fair lock
Fair lock Multiple threads acquire locks in the order of applying for locks , The thread goes directly into the queue to queue , Always be the first in the queue to get the lock .( For example, when a bank does business, it gets a number )
The advantages of this lock are obvious , Each thread is able to acquire resources , The disadvantages are obvious , If a thread is blocked , Other threads will also block , However cpu Wakeup costs a lot , I told you before
Not fair lock Multiple threads try to acquire the lock , If you can't get it, you will enter the waiting queue ,cpu There is no need to wake up
The advantages and disadvantages are just opposite to the above , Advantages reduce overhead , The disadvantages are obvious , It may lead to failure to acquire the lock all the time or failure to acquire the lock for a long time
good , With the basic concept , Let's move on
NonfairSync
First , Let's look at the unfair lock , By default , We applied for unfair locks , That is to say new ReentrantLock(), Let's look at the source code
static final class NonfairSync extends Sync { private static final long serialVersionUID = 7316153563782823691L; /** * Performs lock. Try immediate barge, backing up to normal * acquire on failure. */ final void lock() { if (compareAndSetState(0, 1)) setExclusiveOwnerThread(Thread.currentThread()); else acquire(1); } protected final boolean tryAcquire(int acquires) { return nonfairTryAcquire(acquires); }}
It inherited Sync,Sync Is a content static abstract class :
abstract static class Sync extends AbstractQueuedSynchronizer {…}
Divided into fair and unfair , Use AQS State to indicate the number of times the lock is held , When initializing the constructor sync = …, Let's move on NonfairSync. In use , We call lock.lock() Method , It is ReentrantLock An example method of
// Get the lock public void lock() { sync.lock(); }
In fact, the interior has been adjusted sync Internal method of , Because we applied for an unfair lock , So let's see NonfairSync Under the lock Realization :
final void lock() { if (compareAndSetState(0, 1)) setExclusiveOwnerThread(Thread.currentThread()); else acquire(1);}
compareAndSetState This method , yes AQS Internal method of , This means that if the current state value is equal to the expected value , The synchronization status is automatically set to the given update value . This operation has volatile Memory semantics of read and write .
protected final boolean compareAndSetState(int expect, int update) { // See below for intrinsics setup to support this return unsafe.compareAndSwapInt(this, stateOffset, expect, update);}
You can see the execution lock Method , Will pass AQS Mechanism count ,setExclusiveOwnerThread Set thread exclusive access , It is AbstractOwnableSynchronizer An internal method of , Subclasses use it to manage thread exclusivity
public abstract class AbstractQueuedSynchronizer extends AbstractOwnableSynchronizer implements java.io.Serializable {}
You can see that it inherits AbstractOwnableSynchronizer. Let's see next , We say that if the actual value is equal to the expected value, the above method will be executed , It will be executed when it is not expected acquire(1)
public final void acquire(int arg) { if (!tryAcquire(arg) && acquireQueued(addWaiter(Node.EXCLUSIVE), arg)) selfInterrupt();}
This method gets in exclusive mode , Ignore interrupt , It will try to call tryAcquire, Success will return to , Failed to enter the thread queue , You can repeat blocking and unblocking . look down AQS Internal method . Here I would like to recommend an architecture learning exchange circle . Exchange learning guidance pseudo Xin :1253431195( There are a lot of interview questions and answers ) It will share some videos recorded by senior architects : Yes Spring,MyBatis,Netty Source code analysis , High concurrency 、 High performance 、 Distributed 、 Principles of microservice architecture ,JVM performance optimization 、 Distributed architecture and other necessary knowledge systems for Architects . You can also get free learning resources , Now it's been a lot of good
protected boolean tryAcquire(int arg) { throw new UnsupportedOperationException();}
We can see that the implementation is definitely not here , Its concrete realization lies in NonfairSync
protected final boolean tryAcquire(int acquires) { return nonfairTryAcquire(acquires); }
You can see that it calls ,nonfairTryAcquire Method , This method is unfair tryLock, The concrete realization is Sync Inside , Here we should focus on
final boolean nonfairTryAcquire(int acquires) { final Thread current = Thread.currentThread(); // Returns the synchronization status value , It is AQS An internal method // private volatile int state; // protected final int getState() { // return state; // } int c = getState(); if (c == 0) { // by 0 Just compare , If it is the same as expected, it is set as exclusive thread , It means that the lock has been obtained if (compareAndSetState(0, acquires)) { setExclusiveOwnerThread(current); return true; } } // otherwise Judge if the current thread has been set to exclusive thread else if (current == getExclusiveOwnerThread()) { // Set the current thread state value + 1 And return to success int nextc = c + acquires; if (nextc < 0) // overflow throw new Error(“Maximum lock count exceeded”); setState(nextc); return true; } // Otherwise return to failure I didn't get the lock return false;}
good , Let's look back acquire
public final void acquire(int arg) { // If the current thread does not acquire the lock also If the thread in the queue attempts to hold the lock repeatedly, it will return true, Will call selfInterrupt if (!tryAcquire(arg) && acquireQueued(addWaiter(Node.EXCLUSIVE), arg)) selfInterrupt(); }
selfInterrupt Well understood. , Thread the interrupt
static void selfInterrupt() { Thread.currentThread().interrupt(); }
In fact, our focus is on this method acquireQueued, First, let's look at the input parameters , It passes in a addWaiter, Finally it goes back NODE node
private Node addWaiter(Node mode) { // mode There's nothing to say. It's just a sign , Used to mark exclusive mode static final Node EXCLUSIVE = null; 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.prev = pred; if (compareAndSetTail(pred, node)) { pred.next = node; return node; } } enq(node); return node; }
We can generally guess from ,Node Is a waiting queue node class , Is a linked list structure , Before we talked about FutureTask This structure has been encountered in the source code , It is usually used for spin locks , In this place , It is used to block the synchronizer
+------+ prev +-----+ +-----+head | | <---- | | <---- | | tail +------+ +-----+ +-----+
good , Let's focus on acquireQueued
final boolean acquireQueued(final Node node, int arg) { boolean failed = true; try { // The default is false boolean interrupted = false; // Enter blocking loop traversal The thread queue for (; { // Go back to the previous node final Node p = node.predecessor(); // Judge if the previous node is the head node , And got the lock , The current node will be set as the head node if (p == head && tryAcquire(arg)) { setHead(node); // Here you can see the comments help gc , p.next = null; // help GC failed = false; return interrupted; } // Check and update the status of the node that failed to get . If the thread should block , Then return to true And the thread is interrupted if (shouldParkAfterFailedAcquire(p, node) && parkAndCheckInterrupt()) interrupted = true; } } finally { // If you fail Cancel the node you are trying to get if (failed) cancelAcquire(node); }}
From the source code above , After experiencing the concept of unfair lock mentioned above , Is it better to understand , Then release the lock unlock, This method we can see is ReentrantLock The next instance method , Therefore, the method of releasing the fair lock is also called , In fact, you can finally guess that the call is still sync Methods
public void unlock() { sync.release(1); }
Sync Inherit AQS,release yes AQS Internal method of
public final boolean release(int arg) { // Try to release the lock tryRelease stay Sync Inside if (tryRelease(arg)) { Node h = head; // If the node exists And the status value is not 0 if (h != null && h.waitStatus != 0) // Wake up next node unparkSuccessor(h); return true; } return false; }
private void unparkSuccessor(Node node) { int ws = node.waitStatus; if (ws < 0) compareAndSetWaitStatus(node, ws, 0); 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) // You can see the call LockSupport Wake up LockSupport.unpark(s.thread); }
Let's take another look tryRelease, This implementation is also implemented in Sync Inside
protected final boolean tryRelease(int releases) { // Also, when releasing the lock Still used AQS Count int c = getState() - releases; // Determine whether the current thread is exclusive , It's not throwing an exception if (Thread.currentThread() != getExclusiveOwnerThread()) throw new IllegalMonitorStateException(); boolean free = false; // If it is 0 Indicates that the release is successful if (c == 0) { free = true; // And set the exclusive thread to null setExclusiveOwnerThread(null); } // Update status values setState; return free; }
FairSync
Fair lock FairSync The difference is that , Its implementation of acquiring locks is inside it ,Sync The default internal implementation of the unfair lock
static final class FairSync extends Sync { private static final long serialVersionUID = -3000897897090466540L; // This method eventually calls tryAcquire final void lock() { acquire(1); } // The realization of fair lock protected final boolean tryAcquire(int acquires) { final Thread current = Thread.currentThread(); int c = getState(); // This is similar to the implementation of unfair locks Also judge the status if (c == 0) { // Determine whether the queue exists , Does not exist and compares expectations if (!hasQueuedPredecessors() && compareAndSetState(0, acquires)) { // Set exclusive thread And return to success setExclusiveOwnerThread(current); return true; } } // This side is similar to the above else if (current == getExclusiveOwnerThread()) { int nextc = c + acquires; if (nextc < 0) throw new Error(“Maximum lock count exceeded”); setState(nextc); return true; } return false; } }
Its implementation is relatively simple , Through the implementation, we can find , It acquires locks in the order in which they are requested , The first one gets the lock first , In combination with the above concepts to understand , That makes sense .
Release the lock unlock, As we have already mentioned above ~
Conclusion
This section may be a little too much , It mainly depends on the source code , You can interrupt and adjust yourself , The lines , Understand what fair locks and unfair locks are through the source code , ReentrantLock Where is the reentrant lock experience .
边栏推荐
- 数据库系统原理与应用教程(041)—— MySQL 查询(三):设置查询条件
- 知识图谱:基本概念
- Dynamic planning daily practice (1)
- 【 Visual Dispatching Software】 Shanghai Dow Ning apporte netronic download, Trial, tutoriel pour l'Organisation SMB
- NFT 交易市场的格局之变:从一家独大到百家争鸣
- Machine learning, Wu Enda, logical regression
- How to deal with the new development mode when doing testing?
- 数据库系统原理与应用教程(040)—— MySQL 查询(二):设置要查询的列名或表达式
- Debug No5 basic lighting
- Shell operator, $((expression)) "or" $[expression], expr method, condition judgment, test condition, [condition], comparison between two integers, judgment according to file permission, judgment accor
猜你喜欢

解决MySQL向表中增加数据插入中文乱码问题

2022暑假软件创新实验室集训 项目实战1

Don't be silly to distinguish these kinds of storage volumes of kubernetes

Special lecture 5 combinatorial mathematics learning experience (long-term update)

keepalived双机热备

【JS高级】正则入门基础—关于你想知道的正则表达式_01

Client does not support authentication protocol requested by server; consider upgrading MySQL client
![[visual scheduling software] Shanghai daoning brings netronic downloads, trials and tutorials to SMB organizations](/img/2f/ea0d6ceefca84ef4aeef9c384861f9.png)
[visual scheduling software] Shanghai daoning brings netronic downloads, trials and tutorials to SMB organizations

Wu Enda machine learning series p31~p42

Kotlin - Job 任务/取消
随机推荐
ROS2自学笔记:URDF机器人建模
【JS高级】正则入门基础—关于你想知道的正则表达式_01
Shell operator, $((expression)) "or" $[expression], expr method, condition judgment, test condition, [condition], comparison between two integers, judgment according to file permission, judgment accor
概率沉思录:2.The quantitative rules
Machine learning, Wu Enda, logical regression
General contents of radar introduction column
知识图谱:基本概念
接口测试-简单的接口自动化测试Demo
Hardware system architecture of 4D millimeter wave radar
高性能JVM的参数
Point target simulation of SAR imaging (I) -- mathematical model
Deep understanding of the underlying framework of wechat applet (I)
养老机构智能视频监控解决方案,用新技术助力养老院智慧监管
基于BIM+3DGIS的智慧城市基础设施管理
ES6——周考题
"Computing beast" Inspur nf5468a5 GPU server open trial free application
Optimising a 3D convolutional neural network for head and neck computed tomography segmentation with
Typora 修改表格宽度
The principle of Google interview questions is to analyze 12 table tennis balls, one of which is defective. Weigh it with a balance for 3 times to find it
概率沉思錄:2.The quantitative rules