AQS的release方法为什么不能唤醒被acquire阻塞的应用

来源:4-11 Redis集群

qq_君君晨晨_0

2020-10-03

这里我实现了AQS中的tryAcquire和tryRelease方法,我想的是调用tryAcquire返回fasle会阻塞线程,这个确实做到了,但是我调用tryRelease返回true却不能释放锁。

具体流程:我创建了一个AQS,然后把它传入到线程中,在参数为1的线程中获得共享资源(tryAcquire返回true),在参数为2的线程中阻塞(tryAcquire返回false),然后我想的是当参数为1的线程释放掉锁之后,参数为2的线程应该可以被唤醒然后继续执行,然而事实是参数2的线程在参数1线程释放掉锁后依旧阻塞。

class runnable implements Runnable{
    int arg;
    MyAbstractQuenedSynchronizer aqs;
    @Override
    public void run() {
        try {
            if(arg!=1){
                System.out.println("被阻塞"+Thread.currentThread());
            }
            aqs.acquire(arg);
            System.out.println("开始执行"+Thread.currentThread());
            Thread.sleep(3000);
            System.out.println("执行结束"+Thread.currentThread());
            aqs.release(1);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
    public runnable(int arg,MyAbstractQuenedSynchronizer aqs){
        this.aqs = aqs;
        this.arg = arg;
    }
}

public class MyAbstractQuenedSynchronizer extends AbstractQueuedSynchronizer{
    @Override
    protected boolean tryAcquire(int arg) {
        //参数是1可以,其它不可以
        if(arg==1){
            setExclusiveOwnerThread(Thread.currentThread());
            return true;
        }else{
            return false;
        }
    }

    @Override
    protected boolean tryRelease(int arg) {
        System.out.println("释放锁"+Thread.currentThread());
        setExclusiveOwnerThread(null);
        return true;
    }

    public static void main(String[] args) {
        MyAbstractQuenedSynchronizer aqs = new MyAbstractQuenedSynchronizer();
        new Thread(new runnable(1,aqs)).start();
        new Thread(new runnable(2,aqs)).start();
        new Thread(new runnable(2,aqs)).start();

    }
}

实际输出:
开始执行Thread[Thread-0,5,main]
被阻塞Thread[Thread-2,5,main]
被阻塞Thread[Thread-1,5,main]
执行结束Thread[Thread-0,5,main]
释放锁Thread[Thread-0,5,main]

可以看出来,释放掉锁后其它线程依旧阻塞。

写回答

1回答

qq_君君晨晨_0

提问者

2020-10-04

这个我看了以下源码已经会了,因为release唤醒被阻塞的线程后,被唤醒的线程还会调用tryAcquire方法,按我写的这个它不会获取成功,会再次进入阻塞。

1
0

剑指Java面试-Offer直通车 百度资深面试官授课

招聘季即将到来,让百度资深面试官来为你的高薪Offer保驾护航

8427 学习 · 1870 问题

查看课程