Java并发--阻塞队列的实现原理

阻塞队列的实现原理

使用通知模式实现。 所谓通知模式,就是当生产者往满的队列里添加元素时会阻塞住生产者,当消费者消费了一个队列中的元素后,会通知生产者当前队列可用。通过查看JDK源码发现ArrayBlockingQueue使用了Condition来实现,代码如下。

在这里插入图片描述
当往队列里插入一个元素时,如果队列不可用,那么阻塞生产者主要通过LockSupport.park(this)来实现。
在这里插入图片描述
继续进入源码,发现调用setBlocker先保存一下将要阻塞的线程,然后调用unsafe.park阻塞当前线程。

在这里插入图片描述
unsafe.park是个native方法,代码如下。
在这里插入图片描述

park这个方法会阻塞当前线程,只有以下4种情况中的一种发生时,该方法才会返回。

  • 与park对应的unpark执行或已经执行时。“已经执行”是指unpark先执行,然后再执行park的情况。
  • 线程被中断时。
  • 等待完time参数指定的毫秒数时。
  • 异常现象发生时,这个异常现象没有任何原因。

继续看一下JVM是如何实现park方法:park在不同的操作系统中使用不同的方式实现,在Linux下使用的是系统方法pthread_cond_wait实现。实现代码在JVM源码路径src/os/linux/vm/os_linux.cpp里的os::PlatformEvent::park方法,代码如下。
在这里插入图片描述
pthread_cond_wait是一个多线程的条件变量函数,cond是condition的缩写,字面意思可以理解为线程在等待一个条件发生,这个条件是一个全局变量。这个方法接收两个参数:

一个共享变量_cond,一个互斥量_mutex。

而unpark方法在Linux下是使用pthread_cond_signal实现的。

park方法在Windows下则是使用WaitForSingleObject实现的。想知道pthread_cond_wait是如何实现的,可以参考glibc-2.5的nptl/sysdeps/pthread/pthread_cond_wait.c。

当线程被阻塞队列阻塞时,线程会进入WAITING(parking)状态。我们可以使用jstack dump阻塞的生产者线程看到这点,如下。

在这里插入图片描述

发布了645 篇原创文章 · 获赞 1877 · 访问量 23万+

猜你喜欢

转载自blog.csdn.net/cold___play/article/details/104062933