Java源码解析阻塞队列ArrayBlockingQueue介绍

2025-05-29 0 107

java的阻塞队列,在实现时,使用到了lock和condition,下面是对其主要方法的介绍。

首先看一下,阻塞队列中使用到的锁。

?

1

2

3

4

5

6
/** main lock guarding all access **/

final reentrantlock lock;​

/** condition for waiting takes **/

private final condition notempty;​

/** condition for waiting puts **/

private final condition notfull;

主要的锁是一个可重入锁,根据注释,它是用来保证所有访问的同步。此外,还有2个condition,notempty用于take等待,notfull用于put等待。

两个condition的初始化方法如下:

?

1

2

3

4

5

6

7

8
public arrayblockingqueue(int capacity, boolean fair) {

if (capacity <= 0)

throw new illegalargumentexception();

this.items = new object[capacity];

lock = new reentrantlock(fair);

notempty = lock.newcondition();

notfull = lock.newcondition();

}

下面介绍一下put方法。代码如下。

?

1

2

3

4

5

6

7

8

9

10

11

12
public void put(e e) throws interruptedexception {

checknotnull(e);

final reentrantlock lock = this.lock;

lock.lockinterruptibly();

try {

while (count == items.length)

notfull.await();

enqueue(e);

} finally {

lock.unlock();

}

}

进行put时,首先对待插入的元素进行了非null判断。然后获取锁。之后用一个循环进行判断,如果元素已满,那么,就调用notfull的await方法,进行阻塞。当有别的线程(其实是take元素的线程)调用notfull的siginal方法后,put线程会被唤醒。唤醒后再确认一下count是否小于items.length,如果是,则进行加入队列的操作。

下面介绍一下take方法,代码如下:

?

1

2

3

4

5

6

7

8

9

10

11
public e take() throws interruptedexception {

final reentrantlock lock = this.lock;

lock.lockinterruptibly();

try {

while (count == 0)

notempty.await();

return dequeue();

} finally {

lock.unlock();

}

}

进行take时,同样先要获取锁,然后判断元素个数是否为0,为0时需要等待在notempty条件上,等待被唤醒。唤醒之后,会再进行一次元素个数判断,然后进行出队列操作。

分析代码到这里的时候,我产生了一个疑问,如果当前队列慢了,执行put的线程在获取到锁之后,等待notfull条件上。那么,当执行take操作的线程想获取锁时,阻塞队列的锁已经被前面put的线程获取了,那么take将永远得不到机会执行。怎么回事呢?

后来,我查了condition的await方法,它的注释如下:

  • causes the current thread to wait until it is signalled or interrupted.
  • the lock associated with this condition is atomically released and the current thread becomes disabled for thread scheduling purposes and lies dormant until one of four things happens……

原因在await方法的作用上。因为condition是通过lock创建的,而调用condition的await方法时,会自动释放和condition关联的锁。所以说,当put线程被阻塞后,它实际已经释放了锁了。所以,当有take线程想执行时,它是可以获取到锁的。

另一个问题:当等待在condition上的线程被唤醒时,因为之前调用await前,已经获取了锁,那么被唤醒时,它是自动就拥有了锁,还是需要重新获取呢?

在await方法的注释中,有如下的一段话:

  • in all cases, before this method can return the current thread must re-acquire the lock associated with this condition. when the thread returns it is guaranteed to hold this lock.

说明当等待在condition上的线程被唤醒时,它需要重新获取condition关联的锁,获取到之后,await方法才会返回。

总结

以上就是这篇文章的全部内容了,希望本文的内容对大家的学习或者工作具有一定的参考学习价值,谢谢大家对快网idc的支持。如果你想了解更多相关内容请查看下面相关链接

原文链接:https://blog.csdn.net/li_canhui/article/details/84100166

收藏 (0) 打赏

感谢您的支持,我会继续努力的!

打开微信/支付宝扫一扫,即可进行扫码打赏哦,分享从这里开始,精彩与您同在
点赞 (0)

声明:本站所有文章,如无特殊说明或标注,均为本站原创发布。任何个人或组织,在未征得本站同意时,禁止复制、盗用、采集、发布本站内容到任何网站、书籍等各类媒体平台。如若本站内容侵犯了原著者的合法权益,可联系我们进行处理。

快网idc优惠网 建站教程 Java源码解析阻塞队列ArrayBlockingQueue介绍 https://www.kuaiidc.com/109551.html

相关文章

发表评论
暂无评论