当前位置:网站首页>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
边栏推荐
- Learning and understanding of four special data types of redis
- 大家有遇到CDC读MySQL字段不全的情况吗?怎么处理的?
- Do you really understand code rollback?
- Review in the sixth week
- Kotlin中lateinit和lazy的原理区别是什么
- Daffodils (day 78)
- Greenplum [deployment 08] database small version upgrade process and problem handling error: open-source-greenplum-db-6 conflicts with
- SkyWalking分布式系统应用程序性能监控工具-中
- Smart pointer shared_ ptr、unique_ ptr、weak_ ptr
- 电商系统结合商品秒杀活动,VR全景不断带来收益
猜你喜欢

NFT digital collection system development: old brand literary magazines play with trendy Digital Collections

Feitengtengrui d2000 won the "top ten hard core technologies" award of Digital China

Implementation of API short message gateway based on golang

SkyWalking分布式系统应用程序性能监控工具-中

Solution to Chinese garbled code in console header after idea connects to database to query data

Principle understanding and application of hash table and consistent hash

Vector to SVG method

Golang发送邮件库email

分享当下人生——一个高中毕业生在中央电视台的六星期实习经历

Chapter 4 decision tree and random forest
随机推荐
H.265网页播放器EasyPlayer对外开放录像的方法
It's confirmed that the registration of soft exam in the second half of 2022 will start in August
Digital analog 1232
【无标题】
Learning and understanding of four special data types of redis
Implementation of API short message gateway based on golang
科目三: 济南章丘二号线
商业打假系列之第一百之--无聊的制度和管理流程真的可以扔进垃圾桶-顺便分析十几个无用的Unity游戏自检项目
C. Cypher
04. Detailed steps for installing the simulated browser chromedriver in Google browser
C. Cypher
Cocos game practice-04-collision detection and NPC rendering
真正意义上的数字零售应当具有更加丰富的内涵和意义
222. Number of nodes of complete binary tree
Framework学习之旅:init 进程启动过程
分享当下人生——一个高中毕业生在中央电视台的六星期实习经历
Maximum continuous subsequence (day 77)
代码回滚,你真的理解吗?
Machine learning [Matplotlib]
Worthington papain dissociation system solution