LockSupport 源码阅读

简介:

在java中,要让线程等待最普通的方法是调用Object.wait()方法,

Causes the current thread to wait until another thread invokes the notify() method for this object.

但是当我阅读JUC(java.util.concurrent)的源码时发现这个包不是这样做的, 我跟踪CountDownLatch.await()调用,最后跟到了LockSupport.park()方法里, 这里调用的是 unsafe.park()方法来block线程。

LockSupport 和 CAS一样是JUC很多控制机制的基础(但他们的底层其实都是在依赖Unsafe),下面就来学习下LockSupport这个类:


// Hotspot implementation via intrinsics API
private static final Unsafe unsafe = Unsafe.getUnsafe(); //unsafe 用来实现底层操作
private static final long parkBlockerOffset; //辅助参数,配合unsafe用的

//This object is recorded while
// the thread is blocked to permit monitoring and diagnostic tools to
// identify the reasons that threads are blocked.
//设置一个线程和关联的blocker对象,blocker用来做分析,debug用的
private static void setBlocker(Thread t, Object arg) {
// Even though volatile, hotspot doesn’t need a write barrier here.
unsafe.putObject(t, parkBlockerOffset, arg);
}

//block当前线程,是否真的block了取决于permit是否available
//permit相当于1,0的开关, 默认是0, 调一次unpark就+1变成1了,调一次park会消费这个1又变成0了(park立即返回),
//再次调用park会变成block(因为没有1可以拿了,会等在这,直到有1),这时调用unpark会把1给回去(线程解锁返回)
//每个线程都有个相关的permit, permit最多一个,调用unpark多次也不会积累
//当为permit available时,方法会立即返回,不会block,反之就会block当前线程直到下面3件事发生
//1. 其他线程调用了unpark(此线程)
//2. 其他线程interrupts了此线程
//3. The call spuriously (that is, for no reason) returns.
public static void park() {
unsafe.park(false, 0L);
}

//对于给定线程,让permit变得avaliable,
public static void unpark(Thread thread) {
if (thread != null)
unsafe.unpark(thread);
}

//然后park有2个带限定时间的版本,所以一共有3个park version, 这3个version又有带blocker的debug版本
public static void parkNanos(long nanos) {
public static void parkUntil(long deadline) {

下面写些代码试下


System.out.println("start");
LockSupport.parkNanos(1000000000);
System.out.println("end");
//一开始会block线程,直到给定时间过去后才往下走

System.out.println(“start”);
LockSupport.unpark(Thread.currentThread());
LockSupport.parkNanos(1000000000);
System.out.println(“end”);
//不会block,因为一开始给了一个permit

System.out.println(“start”);
LockSupport.unpark(Thread.currentThread());
LockSupport.unpark(Thread.currentThread());
LockSupport.parkNanos(1000000000);
System.out.println(“inter”);
LockSupport.parkNanos(1000000000);
System.out.println(“end”);
//第一个park不会block,第2个会,因为permit不会因为多次调用unpark就积累

相关文章
|
6月前
AQS源码解读之一
AQS源码解读之一
23 0
|
6月前
|
存储 Dubbo Java
JUC第二十五讲:JUC线程池-CompletableFuture 实现原理与实践
JUC第二十五讲:JUC线程池-CompletableFuture 实现原理与实践
|
6月前
|
监控
JUC第二十九讲:JUC工具类: Phaser详解
JUC第二十九讲:JUC工具类: Phaser详解
|
11月前
|
Java API
【JUC基础】09. LockSupport
LockSupport是一个线程阻塞工具,可以在线程任意位置让线程阻塞。线程操作阻塞的方式其实还有Thread.suspend()和Object.wait()。而LockSupport与suspend()相比,弥补了由于resume()方法而导致线程被挂起(类似死锁)的问题,也弥补了wait()需要先获得某个对象锁的问题,也不会抛出InterruptedException异常。
|
缓存 Java 调度
JUC系列学习(一):线程池Executor框架及其实现ThreadPoolExecutor
`Executor` 框架将任务的提交与任务的执行**解耦**了。
|
Java API Android开发
JUC系列学习(二):AbstractQueuedSynchronizer同步器框架及相关实现类
在并发编程中,我们经常用到的是`synchronized`和`ReentrantLock`。其中,`synchronized`是`jvm`内置锁,而`ReentrantLock`位于`java.util.concurrent`包下(以下简称`JUC`),`ReentrantLock`是基于`AbstractQueuedSynchronizer`(以下简称`AQS`)同步器框架实现的,本文主要来介绍`AQS`的内部实现及在`JUC`中基于`AQS`实现的相关类。
|
Java 调度
锁原理分析系列——LockSupport工具类
锁原理分析系列——LockSupport工具类
79 0
|
并行计算 算法 Java
JUC - ForkJoin
JUC - ForkJoin
78 0
|
设计模式 Java
JUC并发编程——AQS源码解读
JUC并发编程——AQS源码解读
150 0
JUC并发编程——AQS源码解读
|
Java uml
JUC之ThreadPoolExecutor实现原理分析
ThreadPoolExecutor工作流程 JDK1.5中引入了线程池,合理地利用线程池能有效的提高程序的运行效率,但不当的使用线程池也会带来致命的危害。作为使用最多的ThreadPoolExecutor,很有必要深入理解的其源码与实现原理。 先看一下ThreadPoolExecutor是如何工作的,暂时不看源码,这样会先有一个比较直观的印象有利于后面深入分析源码。 既然是线程池那么提交任务后一定要创建线程用于执行任务,ThreadPoolExecutor创建线程执行提交任务的流程如下。
78 0
JUC之ThreadPoolExecutor实现原理分析