" LockSupport 是 JUC 中常用的一个工具类,主要作用是挂起和唤醒线程。在阅读 JUC 源码中经常看到,所以很有必要了解一下。下面会介绍源码中的注释,以及一步一步用代码去验证一些猜想。"
在多线程的场景下,我们会经常使用加锁,来保证线程安全。如果锁用的不好,就会陷入死锁,我们以前可以使用Object的wait/notify来解决死锁问题。也可以使用Condition的await/signal来解决,当然最优还是LockSupport的park/unpark。他们都是解决线程等待和唤醒的。下面来说说具体的优缺点和例子证明一下。
在使用park与unpark的时候就在疑惑为什么先调用unpark时后park就不会阻塞,现在就总结一下原理
LockSupport底层使用UNSAFE类进行操作,UNSAFE类均是使用native方法。
AQS 是实现各种业务 Lock 的基础框架,例如ReentrantLock的实现底层就是使用 AQS。我们可以参考ReentrantLock来实现自己特定需求的 Lock 逻辑。
我们一般都说这个方法是用来中断线程的,那么这个中断应该怎么理解呢?就是说把当前正在执行的线程中断掉,不让它继续往下执行吗?
LockSupport是一个工具类,提供了基本的线程阻塞和唤醒功能,它是创建锁和其他同步组件的基础工具,内部是使用sun.misc.Unsafe类实现的。
位于rt.jar包的java.util.concurrent.locks目录中, 主要作用是挂起和唤醒线程,该工具类是创建锁和其他同步类的基础。
LockSupport类为构建锁和同步器提供了基本的线程阻塞唤醒原语,JDK中我们熟悉的AQS基础同步类就使用了它来控制线程的阻塞和唤醒,当然还有其他的同步器或锁也会使用它。也许我们更加熟悉的阻塞唤醒操作是wait/notify方式,它主要以Object的角度来设计。而LockSupport提供的park/unpark则是以线程的角度来设计,真正解耦了线程之间的同步。为了更好地理解JDK的这些并发工具,我们需要具体分析一下该类的实现。该类主要包含两种操作,分别为阻塞操作和唤醒操作。
java.util.concurrent 中源码频繁使用的 LockSupport 来阻塞线程和唤醒线程,如 AQS 的底层实现用到 LockSupport.park()方法和 LockSupport.unpark()方法。
LockSupport类是java.util.concurrent包中各种锁实现的基础。了解LockSupport的内部机制,对于我们理解concurrent包中的各种锁的实现有很大帮助。
LockSupport是一个线程阻塞工具,可以在线程任意位置让线程阻塞。线程操作阻塞的方式其实还有Thread.suspend()和Object.wait()。而LockSupport与suspend()相比,弥补了由于resume()方法而导致线程被挂起(类似死锁)的问题,也弥补了wait()需要先获得某个对象锁的问题,也不会抛出InterruptedException异常。
LockSupport是JUC包下的一个类,是用来创建锁和其他同步类的基本线程阻塞原语。
此篇博客所有源码均来自JDK 1.8 在线程获取同步状态时如果获取失败,则加入CLH同步队列,通过通过自旋的方式不断获取同步状态,但是在自旋的过程中则需要判断当前线程是否需要阻塞,其主要方法在acquireQueued(): if (shouldParkAfterFailedAcquire(p, node) && parkAndCheckInterrupt()) interrupted = true; 通过这段代码我们可以看到,
在前面学习过java线程间通信的几种方式,分别是synchronized结合wait/notify。以及ReentrantLock结合Condation的await和signal方法。那么实际上还有一种方法也能实现线程通信,那就是LockSupport。我们来看看其源码。
最开始打算分析ReentrantLock,但是分析到最后,发现离不开LockSuport的支持,所以,索性就先开始分析LockSupport,因为它是锁中的基础,是一个提供锁机制的工具类,所以先对其进行分析。
java.util.concurrent.locks.LockSupport 是 Java 并发编程中的一个非常有用的线程阻塞工具类,它包含可以阻塞和唤醒线程的方法。这个类是Java并发编程中的基础工具之一,通常用于构建锁或其他同步组件。LockSupport的所有方法都是静态方法,可以让线程在任意位置阻塞,阻塞之后也有对应的唤醒方法。
JDK中的rt.jar包里面的是个LockSupport是个工具类,它的主要作用是挂起和唤醒线程,该工具类是创建锁和其他同步类的基础。
要想实现多个线程之间的协同,如:线程执行先后顺序、获取某个线程执行的结果等等。 涉及到线程之间相互通信,分为下面四类:
LockSupport工具类定义了一组公共的静态方法,提供了最基本的线程阻塞和唤醒功能,是创建锁和其他同步类的基础,你会发现,AQS中阻塞线程和唤醒线程的地方,就是使用LockSupport提供的park和unpark方法,比如下面这段:
LockSupport中的park()和 unpark()的作用分别是阻塞线程和解除阻塞线程
要想实现多个线程之间的协同,如:线程执行先后顺序、获取某个线程执行的结果等。 涉及到线程之间相互通信,分为如下四类:
等待/通知机制在我们生活中很常见,一个形象的例子就是厨师和服务员之间就存在等待/通知机制。
Java并发编程:多线程如何实现阻塞与唤醒 说到suspend与resume组合有死锁倾向,一不小心将导致很多问题,甚至导致整个系统崩溃。接着看另外一种解决方案,我们可以使用以对象为目标的阻塞,即利用Object类的wait()和notify()方法实现线程阻塞。当线程到达监控对象时,通过wait方法会使线程进入到等待队列中。而当其它线程调用notify时则可以使线程重新回到执行队列中,得以继续执行
park是Unsafe类里的native方法,LockSupport类通过调用Unsafe类的park和unpark提供了几个操作。Unsafe的park方法如下:
该方法主要做了两件事,首先是调用interrupt0,转向JVM做进一步的中断处理,其次是调用blocker.interrupt方法,中断blocker的当前操作,比如堵塞的io读写等。
如果只是LockSupport在使用起来比Object的wait/notify简单,
LockSupport要从wait/notify/notifyAll 、condition.await/signal/signalAll 说起
由上面的代码我们可以看到,如果在调用sleep之前或在sleep过程中,sleep线程被interrupt了,则该sleep方法会抛出InterruptedException异常。
多线程有六种状态:NEW、RUNNABLE、BLOCKED、WAITING、TIMED_WAITING、TERMINATED。
LockSupport是并发工具包中的一个辅助类,在直接的开发过程中很少直接使用,但是它的身影已经遍布各种工具类,众所周知,AbstractQueuedSynchronizer简称(AQS)是Java并发包的基石之一,很多很实用的工具类,如下:
LockSupport是JDK提供的一个线程工具类,它位于rt.jar下面,它的主要作用是挂起和唤醒线程,LockSupport的实现是基于 Unsafe类的,使用LockSupport类的每一个线程都会与它关联一个许可证。
park方法有两个参数来控制休眠多长时间,第一个参数isAbsolute表示第二个参数是绝对时间还是相对时间,单位是毫秒。
一、前言 Basic thread blocking primitives for creating locks and other synchronization classes. 用于创建锁定和其他同步类的基本线程阻塞原语(基础?)。 上面这段话是Java Doc对LockSupport的描述,表明了该类在实现锁当中的重要意义。因此我们先来查看一下其中的源码,看看它是如何实现的。 二、LockSupport成员变量分析 public class LockSupport { private
要想实现线程之间的协同, 如: 线程先后执行顺序, 获取某个线程的执行结果等, 涉及线程之间的相互通信, 分为下面四类
当前队列不为 null,并且 head 的 waitStatus = -1,进入 unparkSuccessor 流程 找到队列中离 head 最近的一个 Node(没取消的),unpark 恢复其运行,本例中即为 Thread-1
首先 一个线程不应该由其他线程来强制中断或停止,而是应该有线程自己自行停止,自己来决定自己的命运。 所以,Thread.stop, Thead.suspend, Thead.resumer都已经被废弃了。
99%的开发者不使用Unsafe类,也可能从未听说过它,但是有1%的开发者使用Unsafe类,这些1%的开发者通常写一些广泛使用的库,使得99%的开发者被传递性地使用Unsafe类(尽管Unsafe类的意图是仅为JDK内部提供服务)。
说明:本篇博客整理自文末的多篇参考博客(每篇博客各有侧重)。本文结合源码对Unsafe的park和unpark方法进行了完整全面的梳理,并对部分参考博客中存在的错误描述进行说明。
如果只是LockSupport在使用起来比Object的wait/notify简单,那还真没必要专门讲解下LockSupport。最主要的是灵活性。
不对呀,我女朋友都没有,哪里的儿子?猛的被惊醒,大白天的,我特么竟然还做上了白日梦!
LockSupport是一个非常方便实用的线程阻塞工具,它可以在线程内任意位置让线程阻塞。和Thread.suspend()相比,它弥补了由于resume()在前发生,导致线程无法继续执行的情况。和Object.wait()方法相比,它不需要先获得某个对象的锁,也不会抛出InterruptedException异常。
重量级锁竞争的时候,还可以使用自旋来进行优化,如果当前线程自旋成功(即这时候持锁线程已经退出了同步块,释放了锁),这时当前线程就可以避免阻塞。 自旋重试成功的情况
而AQS中的控制线程又是通过LockSupport类来实现的,因此可以说,LockSupport是Java并发基础组件中的基础组件。LockSupport定义了一组以park开头的方法用来阻塞当前线程,以及unpark(Thread thread)方法来唤醒一个被阻塞的线程。LockSupport提供的阻塞和唤醒方法如下:
题目 之前参加阿里的面试,其中有道笔试题,当时没有做出,面试之后做出来了。题目如下: 评测题目: 三个线程A、B、C,实现一个程序让线程A打印“A”,线程B打印“B”,线程C打印“C”,三个线程输出ABCABCABC……ABC,循环10次“ABC”。限时30分钟。 代码 下面是我后面写的代码: import java.util.concurrent.locks.LockSupport; public class AliTest { static Thread t1, t2, t3; st
1.文件共享 2.网络共享 3.变量共享 4.jdk提供的线程协调API (重点)
领取专属 10元无门槛券
手把手带您无忧上云