java-基于AQS实现锁
java-基于AQS实现锁
AQS
是AbstractQueuedSynchronizer 抽象队列同步器
1.采用双向链表的数据结构,当多线程同时竞争锁的时候,第一个线程拿到锁后,后续的线程封装成Node节点依次进入同步队列进行排队等待。
2.AQS内部会采取自旋(死循环)的机制,一直判断头节点是否满足获取锁的条件,当锁被第一个线程释放后,队列中头节点条件满足(检查锁的状态是否为0),然后让头节点获取到锁,并脱离队列,如下图:
package me.ele.checkcenter.marketing.util.Test;
import org.jetbrains.annotations.NotNull;
import java.util.Date;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.AbstractQueuedSynchronizer;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
/**
* @author: 谢洪伟
* 2021/6/25 11:40 上午
*/
public class MyLock implements Lock {
private Sync sync = new Sync();
private static class Sync extends AbstractQueuedSynchronizer{
protected Sync() {
super();
}
@Override
protected boolean tryAcquire(int arg) {
// cas比较内存中原始值0,则修改为传入的值
if (compareAndSetState(0, arg)) {
setExclusiveOwnerThread(Thread.currentThread());
return true;
}
return false;
}
@Override
protected boolean tryRelease(int arg) {
if (getState() == 0) {
throw new UnsupportedOperationException();
}
setExclusiveOwnerThread(null);
setState(0);
return true;
}
@Override
protected int tryAcquireShared(int arg) {
return super.tryAcquireShared(arg);
}
@Override
protected boolean tryReleaseShared(int arg) {
return super.tryReleaseShared(arg);
}
/**
* 是否同步独占 true 已被独占 false 未被独占
* @return
*/
@Override
protected boolean isHeldExclusively() {
return getState() == 1;
}
Condition newCondition() {
return new ConditionObject();//AQS已经实现condition
}
}
@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, @NotNull TimeUnit unit) throws InterruptedException {
return sync.tryAcquireNanos(1,unit.toNanos(time));
}
@Override
public void unlock() {
sync.release(1);
}
@NotNull
@Override
public Condition newCondition() {
return sync.newCondition();
}
public static void main(String[] args) {
MyLock lock = new MyLock();
for (int i = 0; i < 10; i++) {
new Thread(()->{
lock.lock();
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
}
System.out.println("time="+new Date());
lock.unlock();
}).start();
}
}
}