当前位置:网站首页>Analyze CAS written by CSDN boss, re-entry lock, unfair lock
Analyze CAS written by CSDN boss, re-entry lock, unfair lock
2022-07-27 04:02:00 【Wage earners~】
Source code :https://blog.csdn.net/kkgbn/article/details/100136988
Add comments you understand to its code
public class MyReentrantLock {
// Used to execute low-level 、 Collection of unsafe operation methods
private static final Unsafe unsafe = getUnsafe();
// Lock handle
private Thread lockHolder;
// This queue updates elements FIFO( fifo ) Sort
private ConcurrentLinkedQueue<Thread> queue = new ConcurrentLinkedQueue<>();
/** * sync . */
private volatile int state;
private static final long stateOffset;
static {
try {
// Object field offset
stateOffset = unsafe.objectFieldOffset(MyReentrantLock.class.getDeclaredField("state"));
} catch (Exception ex) {
throw new Error(ex);
}
}
protected final int getState() {
return state;
}
protected final void setState(int state) {
this.state = state;
}
/** * Compare and set status * @param expect * @param update * @return If successful, then true */
protected final boolean compareAndSetState(int expect, int update) {
return unsafe.compareAndSwapInt(this, stateOffset, expect, update);
}
public Thread getLockHolder() {
return lockHolder;
}
public void setLockHolder(Thread lockHolder) {
this.lockHolder = lockHolder;
}
// CAS as well as Reentrant logic
public boolean tryAcquire() {
// Returns a reference to the currently executing thread object .
final Thread current = Thread.currentThread();
// To obtain state
int c = getState();
if (c == 0) {
// Compare and set status
if (compareAndSetState(0, 1)) {
// Pass in the currently executing thread object
setLockHolder(current);
return true;
}
}
// reentrant ( Reentrant ), current == getLockHolder() Represents the same object
else if (current == getLockHolder()) {
int nextc = c + 1;
if (nextc < 0) // overflow ( state + 1 Less than zero by overflow )
throw new Error("Maximum lock count exceeded");
// Set the status value after adding one
setState(nextc);
return true;
}
return false;
}
public boolean acquire() {
// try acquire
if (tryAcquire()) {
return true;
}
// add queue and spin ( Add queues and rotations )
final Thread current = Thread.currentThread();
// If the status is not 0, The thread object is not a , Then join the queue
queue.add(current);
for (;;) {
// peek : Retrieve but not delete the header of this queue , If this queue is empty , Then return to null .
if (current == queue.peek() && tryAcquire()) {
// TODO CAS
// Retrieve and delete the header of this queue , If this queue is empty , Then return to null .
queue.poll();
return true;
}
// Basic thread blocking primitives for creating locks and other synchronization classes .
LockSupport.park();
}
}
/** * Lock */
public void lock() {
// Compare settings
if (compareAndSetState(0, 1)) {
// Set up the success , Set up Reference to the currently executing thread object .
setLockHolder(Thread.currentThread());
return;
}
// Setup failed , Try to get
acquire();
}
/** * Unlock */
public void unlock() {
Thread current = Thread.currentThread();
if (current != lockHolder) {
throw new IllegalMonitorStateException("can't unlock");
}
int c = getState() - 1;
if (c == 0) {
// Status as 0 , Said the unlock , LockHolder Value is empty
setLockHolder(null);
}
setState(c);
Thread waiter = queue.peek();
// Not empty , Indicates that there are threads in the queue
if (null != waiter) {
// unblocked
LockSupport.unpark(waiter);
}
}
// Unsafe tools
public static Unsafe getUnsafe() {
Unsafe unsafe = null;
try {
Constructor<Unsafe> constructor = Unsafe.class.getDeclaredConstructor(new Class<?>[0]);
constructor.setAccessible(true);
unsafe = constructor.newInstance(new Object[0]);
} catch (Exception e) {
e.printStackTrace();
}
return unsafe;
}
}
Writing test classes
@Slf4j
public class MyLockTest {
public static void main(String[] args) {
MyReentrantLock myReentrantLock = new MyReentrantLock();
new Thread(() -> {
log.debug("{}: Start locking ", Thread.currentThread().getName());
myReentrantLock.lock();
log.debug("{}: After locking , Status as :{}",Thread.currentThread().getName(), myReentrantLock.getState());
// TimeUnit.SECONDS.sleep(2);
myReentrantLock.unlock();
log.debug("{}: Unlock complete ", Thread.currentThread().getName());
log.debug("{}: Unlock complete , Status as :{}",Thread.currentThread().getName(), myReentrantLock.getState());
}, "t").start();
new Thread(() -> {
log.debug("{}: Start locking ", Thread.currentThread().getName());
myReentrantLock.lock();
log.debug("{}: After locking , Status as :{}",Thread.currentThread().getName(), myReentrantLock.getState());
// TimeUnit.SECONDS.sleep(2);
myReentrantLock.unlock();
log.debug("{}: Unlock complete ", Thread.currentThread().getName());
log.debug("{}: Unlock complete , Status as :{}",Thread.currentThread().getName(), myReentrantLock.getState());
}, "t1").start();
}
}
Output results
21:43:39.108 [t1] DEBUG com.xiaozheng.cas.MyLockTest - t1: Start locking
21:43:39.108 [t] DEBUG com.xiaozheng.cas.MyLockTest - t: Start locking
21:44:08.973 [t1] DEBUG com.xiaozheng.cas.MyLockTest - t1: After locking , Status as :1
21:44:08.973 [t1] DEBUG com.xiaozheng.cas.MyLockTest - t1: Unlock complete
21:44:08.973 [t1] DEBUG com.xiaozheng.cas.MyLockTest - t1: Unlock complete , Status as :0
21:44:09.937 [t] DEBUG com.xiaozheng.cas.MyLockTest - t: After locking , Status as :1
21:44:09.937 [t] DEBUG com.xiaozheng.cas.MyLockTest - t: Unlock complete
21:44:09.937 [t] DEBUG com.xiaozheng.cas.MyLockTest - t: Unlock complete , Status as :0
My little summary
- It mainly determines whether the state and thread object are the same object , Whether to lock
- If
State not for 0,The thread object is not the same, ExpressThere are threads competing for locks, It isThread join queue, And temporarilyparkThis thread - When the locking thread finishes executing and unlocks , Will
parkThread evokes , At this point, the thread competing for the lock will re-enter the next round of queue traversal , Get the current thread and set the statuslockHolderIs the current thread - When the unlock ,
State minus 1, by 0 when , Set uplockHolderbynull, Wait for the assignment of the next locking thread , Wake up when the queue is not emptypark
边栏推荐
- leetcode:433. 最小基因变化
- Case when in MySQL returns multiple field processing schemes
- C. Cypher
- Read and understand | how data center supports enterprise digital operation
- Message queue learning -- Concepts
- Function pointer and callback function
- 0726~简历梳理面试总结
- 基于风能转换系统的非线性优化跟踪控制(Matlab代码实现)
- NFT数字藏品系统开发:小蚁数智帮助品牌一键上链发行NFT
- Ming min investment Qiu Huiming: behind the long-term excellence and excess, the test is the team's investment and research ability and the integrity of strategy
猜你喜欢

Process analysis of object creation

函数指针与回调函数

Meta Quest内容生态总监谈App Lab设计初衷

VR全景现在是不是刚需?看完你就明白了

C#怎么实现给Word每一页设置不同文字水印

Plato farm brings a new experience to community users through the LAAS protocol elephant swap

深圳家具展首日,金可儿展位三大看点全解锁!

科目三: 济南章丘五号线

Program to change the priority of the process in LabVIEW

想要获得 Apache 官方域名邮箱吗?专访 Apache Linkis 五位新晋 Committer告诉你怎么做
随机推荐
Meta Quest内容生态总监谈App Lab设计初衷
DataX cannot connect to the corresponding database (yes under windows, but failed under Linux)
Characteristics and experimental suggestions of abbkine abfluor 488 cell apoptosis detection kit
C语言入门实战(12):求自然常数e的值
C. Cypher
Daffodils (day 78)
Characteristics and determination scheme of Worthington pectinase
一文读懂 | 数据中台如何支撑企业数字化经营
Application, addition and deletion of B-tree
C language force deduction question 43 string multiplication. Optimized vertical
Alibaba cloud server domain name and port web page cannot access the problem record
unity之二维数组实现正六边形地图
Program to change the priority of the process in LabVIEW
[Android synopsis] kotlin multithreaded programming (I)
Review in the sixth week
Principle understanding and application of hash table and consistent hash
C. Cypher
Cocos game practice-05-npc and character attack logic
Characteristics and experimental suggestions of abbkine abfluor 488 cell apoptosis detection kit
C# 使用SqlSugar Updateable系统报错无效数字,如何解决?求指导!