当前位置:科普知识站>IT科技>

java|reentrantlock

IT科技 阅读(2.1W)

<link rel="stylesheet" href="https://js.how234.com/third-party/SyntaxHighlighter/shCoreDefault.css" type="text/css" /><script type="text/javascript" src="https://js.how234.com/third-party/SyntaxHighlighter/shCore.js"></script><script type="text/javascript"> SyntaxHighlighter.all(); </script>

java reentrantlock是什么?一起来看下吧:

是一个可重入且独占式的锁,它具有与使用synchronized监视器锁相同的基本行为和语义,但与synchronized关键字相比,它更灵活、更强大,增加了轮询、超时、中断等高级功能。ReentrantLock,顾名思义,它是支持可重入锁的锁,是一种递归无阻塞的同步机制。除此之外,该锁还支持获取锁时的公平和非公平选择。

ReentrantLock的内部类Sync继承了AQS,分为公平锁FairSync和非公平锁NonfairSync。如果在绝对时间上,先对锁进行获取的请求你一定先被满足,那么这个锁是公平的,反之,是不公平的。公平锁的获取,也就是等待时间最长的线程最优先获取锁,也可以说锁获取是顺序的。ReentrantLock的公平与否,可以通过它的构造函数来决定。

事实上,公平锁往往没有非公平锁的效率高,但是,并不是任何场景都是以TPS作为唯一指标,公平锁能够减少“饥饿”发生的概率,等待越久的请求越能够得到优先满足。

ReentrantLock是通过自定义同步器来实现锁的获取与释放,我们以非公平锁(默认)实现为例,对锁的获取和释放进行详解。

获取锁:

public ReentrantLock() {    sync = new NonfairSync();}

即内部同步组件为非公平锁,获取锁的代码为:

public void lock() {    sync.lock();}

释放锁:

成功获取锁的线程在完成业务逻辑之后,需要调用unlock()来释放锁:

public void unlock() {    sync.release(1);}

unlock()调用NonfairSync类的release(int)方法释放锁,release(int)方法是定义在AQS中的方法:

public final boolean release(int arg) {    if (tryRelease(arg)) {        Node h = head;        if (h != null && h.waitStatus != 0)            unparkSuccessor(h);        return true;    }    return false;}

tryRelease(int)是子类需要实现的方法:

protected final boolean tryRelease(int releases) {    // 计算新的状态值    int c = getState() - releases;    // 判断当前线程是否是持有锁的线程,如果不是的话,抛出异常    if (Thread.currentThread() != getExclusiveOwnerThread())        throw new IllegalMonitorStateException();    boolean free = false;    // 新的状态值是否为0,若为0,则表示该锁已经完全释放了,其他线程可以获取同步状态了    if (c == 0) {        free = true;        setExclusiveOwnerThread(null);    }    // 更新状态值    setState(c);    return free;}

如果该锁被获取n次,那么前(n-1)次tryRelease(int)方法必须返回false,只有同步状态完全释放了,才能返回true。可以看到,该方法将同步状态是否为0作为最终释放的条件,当状态为0时,将占有线程设为null,并返回true,表示释放成功。

java reentrantlock