Java knowledge needed in work (AQS articles)

When can I earn 6000 yuan 2022-11-24 20:58:09 阅读数:19

javaknowledgeneededworkaqs

AQSIt is a frequently asked question during interviews,So today we will briefly understand what isAQS.

什么是AQS?

Let's briefly talk about what isAQS,AQS其实是指Java中的AbstractQueuedSynchronizer类,这个类在java.util.concurrent.locks包下,是JavaClass used to implement lightweight locks.

AQS的核心思想是,如果被请求的共享资源空闲,则将当前请求资源的线程设置为有效的工作线程,并将共享资源设置为锁定状态,如果被请求的共享资源被占用,那么就需要一套线程阻塞等待以及被唤醒时锁分配的机制,这个机制AQS是用CLH队列锁实现的,即将暂时获取不到锁的线程加入到队列中.

CLHThe queues are named after the initials of the three inventors.CLHThe queue logically forms a lock waiting queue(There are actually no queue instances,Only through the association between nodes)从而实现加锁,CLH锁Only sequential locking and unlocking is supported(FIFO先入先出),不支持重入,不支持中断.

AQS中还有一个state变量,Used to determine whether the current state is in sync(通过CAS方法来改变state的值),0:资源空闲,当state变量大于0indicates that the resource is being locked,且stateThe value of represents the number of reentries to lock the resource.

AQS的工作流程就是基于CLH虚拟队列,用volatile关键字修饰共享变量state,想要The thread that acquires the lock passesCAS方法去改变state变量,成功则获取到锁,If it fails, it enters the waiting queue and waits for wake-up.

AQSThe design method of the template pattern is adopted

We just need to create our own class following the template,You can generate a custom synchronizer(锁).

First we have to follow these two steps:

1. Inner class synchronizers need to be inheritedAbstractQueuedSynchronizer并重写指定的方法.

2. The outer class synchronizer needs to be implementedLock接口与SerializableThe interface provides external services.

We only need to implement shared variables when we create custom synchronizersstateThe acquisition and release can be,The maintenance of the waiting queue is done by AQS底层实现.

Methods that custom synchronizers need to implement:

方法名作用
isHeldExclusively()该线程是否正在独占资源.只有用到condition才需要去实现它
tryAcquire(int)独占方式.尝试获取资源,成功则返回true,失败则返回false.
tryRelease(int)独占方式.尝试释放资源,成功则返回true,失败则返回false.
tryAcquireShared(int)共享方式.尝试获取资源.负数表示失败;0表示成功,但没有剩余可用资源;正数表示成功,且有剩余资源.
tryReleaseShared(int)共享方式.尝试释放资源,如果释放后允许唤醒后续等待结点返回true,否则返回false.

ReentrantLock为例,(可重入独占式锁):state变量初始化为0,表示未锁定状态,A线程lock()时,会调用tryAcquire()独占锁并将state+1.之后其他线程再想tryAcquire的时候就会失败,直到A线程unlock()到state=0为止,其他线程才有机会获取该锁.AThis lock can be acquired repeatedly before the lock is released(state累加),这就是可重入的概念.
注意:获取多少次锁就要释放多少次锁,保证state是能回到零态的.

CountDownLatch为例,任务分N个子线程去执行,state就初始化为N,N个线程并行执行,每个线程执行完之后countDown()一次,state就会CAS减一.当N子线程全部执行完毕,state=0,会unpark()主调用线程,主调用线程就会从await()函数返回,继续之后的动作.

Next we try to customize a synchronizer.

/**
* @description: 自定义同步器
* @author: Me
* @createDate: 2022/11/21 11:09
* @version: 1.0
*/
public class NonReentrantLock implements Lock, Serializable {
// When a synchronizer is implemented, the custom synchronizer is generally defined as an inner class,供自己使用,and implement an interface,向外提供服务,一般实现Lock接口
// The advantage of inner classes is that they can achieve multiple inheritance in disguise
// Inner classes are hidden from other classes in the same package,内部类可以使用private关键字修饰
// The inner class can access all the fields and methods of the outer class,An outer class accessing an inner class needs to create an inner class object,Inner classes cannot have static members
private static class Sync extends AbstractQueuedSynchronizer{
@Override
protected boolean tryAcquire(int arg) {
assert arg == 1;
// cas方法,将变量0改为1
if (compareAndSetState(0,1)){
// If the modification is successful, it will be locked
setExclusiveOwnerThread(Thread.currentThread());
return true;
}
return false;
}
@Override
protected boolean tryRelease(int arg) {
assert arg == 1;
//如果state为0,则抛出异常
if (getState()==0){
throw new IllegalMonitorStateException();
}
// 如果state变量不为0,则释放锁
setExclusiveOwnerThread(null);
setState(0);
return true;
}
@Override
protected boolean isHeldExclusively() {
// 是否锁已经被持有
return getState() == 1;
}
//提供条件变量接口
public Condition newCondition(){
return new ConditionObject();
}
}
Sync sync = new Sync();
@Override
public void lock() {
sync.acquire(1);
}
@Override
public void lockInterruptibly() throws InterruptedException {
sync.acquireInterruptibly(1);
}
@Override
public boolean tryLock() {
return sync.tryAcquire(1);
}
@Override
public boolean tryLock(long time, TimeUnit unit) throws InterruptedException {
return sync.tryAcquireNanos(1, unit.toNanos(time));
}
@Override
public void unlock() {
sync.release(1);
}
@Override
public Condition newCondition() {
return sync.newCondition();
}
}

到这里AQSJust a brief introduction,希望对小伙伴们有所帮助.

copyright:author[When can I earn 6000 yuan],Please bring the original link to reprint, thank you. https://en.javamana.com/2022/328/202211242055467293.html