AQS阻塞唤醒工具LockSupport


LockSupport在JDK源码中描述为:构建锁和其余同步类的基本线程阻塞原语,构建更高级别的同步工具集。LockSupport提供的park/unpark从线程的粒度上进行阻塞和唤醒,park/unpark模型真正解耦了线程之间的同步,线程之间再也不须要一个Object或者其它变量来存储状态。
html

本文从阻塞唤醒的语义入手,解释LockSupport的内在机制和注意点,最后与Object的wait和notify作对比,包括如下内容:java

  • 阻塞和唤醒的语义
  • 许可机制
  • 底层实现
  • 用法
  • 与Object的wait和notify区别

阻塞的语义

阻塞是线程在知足某种条件以前暂时中止运行,而被动释放出CPU资源。进入该状态的线程不会主动进入线程队列等待CPU资源,而须要等待知足条件后被唤醒,才能让该线程从新进入到线程队列中排队等待CPU资源。通常形成线程阻塞的缘由有:等待获取一个已经被其余线程持有的排他锁、等待某一操做结束、等待某一个时间段。线程阻塞后会被挂起,此时会处于BLOCKEDWAITINGTIMED_WAITING。线程阻塞后会让出CPU资源,这是为避免在自旋上浪费过多的CPU资源,是忙等待(busy wait)的一种优化。微信

许可机制

LockSupport经过“许可”(permit)机制,使用park/unpark实现线程的阻塞和唤醒。许但是指容许线程继续执行,是线程执行的开关,当开关关闭时,线程会阻塞,当开关打开时,线程会当即执行。多线程

park意指线程在获取许可以前会暂停执行(阻塞在获取许可)。这里的“许可”与线程相关联,相似二元信号量,不可叠加且一个线程只能有一个。有些文章描述“许可”是一次性的,例如当线程A调用park消耗掉一个“许可”(最多只有一个“许可”),在未调用unpark释放出线程A的该“许可”以前,线程A再次调用park时会阻塞在获取“许可”。下文引自Understanding JVM Thread States并发

there can be only one permit per thread, when thread consumes the permit, it disappears.app

出于线程调度的目的,调用park时会阻塞直到许可可用时。若是许可可用,调用park就会当即返回。当前线程就会阻塞,直到调用 unpark 方法,释放出许可。因为许但是默认被占用的,当前线程在启动后调用 park 的话就获取不到许可,所以就进入阻塞状态。框架

底层实现

LockSupport是使用Unsafe的park实现的,HotSpot Parker用condition和mutex维护了一个_counter变量,park时,变量_counter置为0,unpark时,变量_counter置为1。park操做检查该值是否为1,为1直接返回;不为1,则阻塞。jvm

用法

看到一个关于park/unpark通俗易懂的的例子,代码以下:ide

 1 public static void main(String[] args) throws InterruptedException {
 2   Thread threadA = new Thread(new Runnable() {
 3     @Override
 4     public void run() {
 5       System.out.println("周末了我在打游戏");
 6       LockSupport.park();
 7       System.out.println("陪女友逛逛街");
 8     }
 9   });
10   threadA.start();
11   Thread.sleep(3000);
12   System.out.println("女友准备要喊男友逛街");
13   LockSupport.unpark(threadA);
14 }

在第6行park执行操做时,线程尝试获取许可,因为线程threadA在启动后默认已经获取了许可,park必须等待许可释放后才能够执行。当主线程调用unpark方法释放threadA的许可,threadA才能够继续执行第7行。 工具

与wait和notify区别

park/unpark与wati/notify都提供阻塞唤醒的功能,用作线程间同步,不过二者 的粒度不一样,park/unpark做用在线程上,而wait/notify做用在对象上,两者没有交集。Object的wait/notify使用前必须获取对象的监视器,而park/unpark不须要。

写做不易,痛并快乐着;理解可能存在误差,句句斟酌推敲;抵制抄袭,践行原创技术之路。若是本文能对您有所帮助,实为荣幸,我是葛一凡。

原文
微信公众号微信公众号

参考

    1. Java的LockSupport.park()实现分析
    2. java线程阻塞中断和LockSupport的常见问题
    3. 多线程之Java线程阻塞与唤醒
    4. Understanding JVM Thread States
    5. java并发包系列—LockSupport
    6. Java并发包源码学习之AQS框架(三)LockSupport和interrupt
相关文章
相关标签/搜索