我们已经了解了AQS的的基本原理了,不如自己仿照其它锁实现一个排他锁吧。
要求如下:同一时间只允许一个线程持有锁,不要求可重入(反复加锁直接忽视即可)。
(1)实现Lock接口
public class Demo23 {
public static void main(String[] args) {
}
private static class myLock implements Lock{
@Override
public void lock() {
}
@Override
public void lockInterruptibly() throws InterruptedException {
}
@Override
public boolean tryLock() {
return false;
}
@Override
public boolean tryLock(long time, TimeUnit unit) throws InterruptedException {
return false;
}
@Override
public void unlock() {
}
@Override
public Condition newCondition() {
return null;
}
}
}
(2) 创建内部类sync继承AQS,内部调用sync完成逻辑
public class Demo23 {
public static void main(String[] args) {
myLock lock = new myLock();
lock.lock();
}
private static class myLock implements Lock{
private class sync extends AbstractQueuedSynchronizer {
@Override
protected boolean tryAcquire(int arg) {
return super.tryAcquire(arg);
}
@Override
protected boolean isHeldExclusively() {
return getExclusiveOwnerThread() == Thread.currentThread();
}
protected 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();
}
}
}
上面代码的运行结果如下。
/home/wangzhou/IdeaProjects/jucdemo/src/com/wangzhou/Demo21.java:11:24
java: 未报告的异常错误java.lang.InterruptedException; 必须对其进行捕获或声明以便抛出
这是因为其父类的tryAcquire方法实现如下。
protected boolean tryAcquire(int arg) {
throw new UnsupportedOperationException();
}
(3)实现tryAcquire
先看看其它锁怎么做的。比如公平锁。
protected final boolean tryAcquire(int acquires) {
final Thread current = Thread.currentThread();
int c = getState();
if (c == 0) {
if (!hasQueuedPredecessors() &&
compareAndSetState(0, acquires)) {
setExclusiveOwnerThread(current);
return true;
}
}
else if (current == getExclusiveOwnerThread()) {
int nextc = c + acquires;
if (nextc < 0)
throw new Error("Maximum lock count exceeded");
setState(nextc);
return true;
}
return false;
}
上面代码包含可重入逻辑,我们这里如果重入直接忽略,返回false,因此核心逻辑就只需要进行一个CAS
操作了。
@Override
protected boolean tryAcquire(int acquires) {
if(isHeldExclusively()) {
return true;
}
if (compareAndSetState(0, acquires)) {
setExclusiveOwnerThread(Thread.currentThread());
return true;
}
return false;
}
加锁过程已经完成,您可以自行测试,接下来我们来实现解锁功能。
同样先看看其它锁怎么实现。
protected final boolean tryRelease(int releases) {
int c = getState() - releases;
if (Thread.currentThread() != getExclusiveOwnerThread())
throw new IllegalMonitorStateException();
boolean free = false;
if (c == 0) {
free = true;
setExclusiveOwnerThread(null);
}
setState(c);
return free;
}
我们要实现的逻辑也很简单,没加锁的情况下不允许解锁。加锁的情况下解锁。
@Override
protected boolean tryRelease(int args) {
if(getState() == 0) {
throw new UnsupportedOperationException();
}
if(isHeldExclusively()) {
setExclusiveOwnerThread(null);
setState(0);
return true;
}
return false;
}
测试.
public static void main(String[] args) throws InterruptedException {
myLock lock = new myLock();
lock.lock();
new Thread(() ->{
lock.lock();
System.out.println("thread2 get lock");
lock.unlock();
}).start();
TimeUnit.SECONDS.sleep(1);
lock.unlock();
System.out.println("thread 1 unlock");
}
condition请读者自测。