java 使用AQS写可重入锁
在上一篇文章中,手动实现了一个可重入锁,在本节中,使用AQS重写这个可重入锁MyLock2类,实现了Lock接口,定义内部类Sync继承自AbstractQueuedSynchronizer,并实现了两个方法,分别为tryAcquire(int arg)和tryRelease(int arg),tryAcquire函数的实现逻辑与上一篇文章"java 手动实现一个可重入锁"中的lock函数一致,而tryRelease函数的实现逻辑与unlock一致。下面给出实现代码,具体的流程见代码注释
package com.concur.class23;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.AbstractQueuedSynchronizer;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
public class MyLock2 implements Lock{
private Sync sync=new Sync();
private class Sync extends AbstractQueuedSynchronizer{
@Override
protected boolean tryAcquire(int arg) {
//当目前并没有线程获得锁时,进来的线程就可以拿到锁,因此返回true
//当有其他线程进来时,1.当前进来的线程和当前保存的线程是同一个线程,则可以拿到锁,但是需要更新状态值 2.若与当前保存的线程
//不是同一个线程,则拿不到锁,返回false
int state=getState();
Thread t=Thread.currentThread();
//若当前并没有线程获得锁,state=0
if(state==0){
//将state的值更新
if(compareAndSetState(0, arg)){
//设置当前独占线程为t
setExclusiveOwnerThread(t);
return true;
}
}
//若当前想要获得锁的线程已经获得锁,即可重入
else if(getExclusiveOwnerThread()==t){
setState(state+arg);
return true;
}
return false;
}
@Override
protected boolean tryRelease(int arg) {
//若当前想要释放锁的线程不是保存的线程,则抛出异常
if(getExclusiveOwnerThread()!=getExclusiveOwnerThread()){
throw new RuntimeException();
}
int state=getState()-arg;
boolean flag=false;
//若state为0,则表明当前没有线程持有锁,则设置为null
if(state==0){
setExclusiveOwnerThread(null);
flag=true;
}
setState(state);
return flag;
}
Condition newCondition(){
return new ConditionObject();
}
}
@Override
public void lock() {
sync.acquire(1);
}
@Override
public void unlock() {
sync.release(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 Condition newCondition() {
return sync.newCondition();
}
}
编写测试类Test用来测试该可重入锁:
package com.concur.class23;
public class Test {
MyLock2 lock=new MyLock2();
public void a(){
lock.lock();
System.out.println("a");
b();
lock.unlock();
}
public void b(){
lock.lock();
System.out.println("b");
lock.unlock();
}
public static void main(String[] args) {
Test t=new Test();
new Thread(new Runnable() {
@Override
public void run() {
t.a();
}
}).start();
}
}
输出结果为:
a
b