使用AQS自己实现一把锁
其实是想一把锁需要两点: 1. 锁状态( 0当前有线程在使用 1当前无线程在使用) 2.持有锁的线程(当前线程)
总结:就是当前如果有线程通过竞争cas成功了,则将 【锁状态】设为1,将持有锁的线程记录起来。 这样就能防止其他线程再获取。
我们知道要是实现一个自定义的 Lock 实现类,首先要实现 Lock 接口,并且定义一个内部类继承 AQS 类,重写他的方法
package com.middle.aqsdemo;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.AbstractQueuedSynchronizer;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
/**
* @author 15510
* @create 2019-07-31 17:10
*/
public class SimplifyReentrantLock implements Lock {
private final Sync sync = new Sync();
/**
* AQS的子类Sync
*/
private static class Sync extends AbstractQueuedSynchronizer {
@Override
protected boolean isHeldExclusively() {
//是否处于占用状态
return getState() == 1;
}
@Override
protected boolean tryAcquire(int arg) {
//当状态为0是获取锁
if (compareAndSetState(0, 1)) {
setExclusiveOwnerThread(Thread.currentThread());
return true;
}
return false;
}
@Override
protected boolean tryRelease(int arg) {
//释放锁,将状态设置为0
if (getState() == 0) {
throw new IllegalMonitorStateException();
}
setExclusiveOwnerThread(null);
setState(0);
return true;
}
Condition newCondition() {
return new ConditionObject();
}
}
@Override
public void lock() { sync.acquire(1); }
@Override
public void unlock() { sync.release(1); }
@Override
public Condition newCondition() { return sync.newCondition(); }
@Override
public boolean tryLock() { return sync.tryAcquire(1); }
@Override
public void lockInterruptibly() throws InterruptedException { }
@Override
public boolean tryLock(long time, TimeUnit unit) throws InterruptedException {
return false;
}
}
package com.middle.aqsdemo;
import java.util.concurrent.locks.Condition;
/**
* @author 15510
* @create 2019-07-31 17:12
*/
public class SimplifyReentrantLockDemo {
public static void main(String[] args) {
SimplifyReentrantLock lock = new SimplifyReentrantLock();
Condition condition = lock.newCondition();
new Thread(() -> {
lock.lock();
try {
System.out.println("进入等待!");
condition.await(); // 释放锁
System.out.println("接收到通知!继续执行!");
} catch (InterruptedException e) {
e.printStackTrace();
}
lock.unlock();
}, "conditionAwaitThread").start();
new Thread(() -> {
try {
System.out.println("模拟3秒后发送通知过!");
Thread.sleep(3000);
} catch (InterruptedException e) {
e.printStackTrace();
}
lock.lock();
System.out.println("发送通知!");
condition.signal();
lock.unlock();
}, "conditionSignalThread").start();
}
}
执行结果
进入等待!
模拟3秒后发送通知过!
发送通知!
接收到通知!继续执行!
Process finished with exit code 0