在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就积累
相关推荐
《深入解析Java并发编程:Unsafe类与LockSupport类源码剖析》 在Java并发编程领域,Unsafe类和LockSupport类是两个重要的底层工具类,它们提供了低级别的内存操作和线程控制,使得开发者能够实现高效的并发算法和...
源码解析文件ScheduledThreadPoolExecutor 在 Java 中,ScheduledThreadPoolExecutor 是一个线程池执行器,用于执行延迟任务。它使用DelayedWorkQueue来实现延迟的效果。下面是 ScheduledThreadPoolExecutor 的实现...
本文将基于JDK源码解析Java领域中的并发锁,探讨AQS基础同步器、LockSupport、Condition接口、Lock接口、ReadWriteLock接口以及自定义API操作的设计与实现。 一、AQS(AbstractQueuedSynchronizer)基础同步器的...
Java并发包源码分析(JDK1.8):囊括了java.util.concurrent包中大部分类的源码分析,其中涉及automic包,locks包(AbstractQueuedSynchronizer、ReentrantLock、ReentrantReadWriteLock、LockSupport等),queue...
在深入理解多线程和同步机制时,阅读和分析JDK源码是很有帮助的。例如,研究`Thread`类、`synchronized`关键字的实现、`LockSupport`类等,可以帮助我们更好地理解Java的并发机制。 综上所述,Java的多线程和同步...
5. **锁的优化**:Java 7引入了弱引用锁(LockSupport.park/unpark),以及自旋锁和可中断锁的优化,使得锁的实现更加灵活和高效。ReentrantLock、ReadWriteLock等接口和类提供了高级锁定机制。 6. **并发工具类**...
通过源码分析,我们可以看到如`LockSupport`、`ForkJoinPool`等是如何工作的。 6. 字符串处理:`java.lang.String`是Java中至关重要的类,OpenJDK源码揭示了字符串的创建、比较、拼接等操作的内部实现,这对于理解...
Disruptor原始代码分解析出(超详细注释),版本3.4.2,方便大家阅读源码,供大家学习使用。项目中使用时请从Disruptor官方发布依赖。 ,欢迎指正。 LMAX破坏者 高性能线程间消息传递库 维护者 文献资料 变更日志 ...
- 同步代码块:使用`synchronized`关键字包裹代码块,锁定特定对象,控制并发访问。 - `wait()`和`notify()`/`notifyAll()`:用于线程间的通信,需在同步环境中使用。 - `ReentrantLock`:可重入锁,提供更灵活的...
LockSupport.park(this); //判断是否被中断 if ((interruptMode = checkInterruptWhileWaiting(node)) != 0) break; } //获取锁,如果获取中被中断则设置中断状态 if (acquireQueued(node, savedState) && ...
4. 等待(Waiting):线程在等待其他线程执行特定操作(如wait()、join()或LockSupport.park())。 5. 定时等待(Timed Waiting):线程在等待一段时间后自动恢复(如Thread.sleep()、Object.wait(long)等)。 6. ...
18.一篇文章,从源码深入详解ThreadLocal内存泄漏问题 19.并发容器之BlockingQueue 20.并发容器之ArrayBlockingQueue和LinkedBlockingQueue实现原理详解 21.线程池ThreadPoolExecutor实现原理 22.线程池之...
在Java编程中,多线程是一项关键特性,它允许程序同时执行多个任务,极大地提高了...《Java 多线程设计模式》一书的源代码应该涵盖了这些知识点的具体实现,通过阅读和实践,可以深入理解多线程编程和设计模式的精髓。
⼀、ReentrantLock重⼊锁 1.1> 概述 1.2> 中断响应 lockInterruptibly() 1.3> 锁申请等待限时 tryLock(long time, TimeUnit unit) 1.4> 公平锁和⾮公平锁 1.5> AQS源码解析 ...七、LockSupport线程阻塞⼯具类
这样做的目的是确保后续代码可以检测到中断请求,特别是对于那些依赖于中断状态的高阶并发工具(如`ExecutorService`,`Future`等)。 下面是一段典型的处理`InterruptedException`的代码示例: ```java try { ...
hashmap源码 to-be-architect to be a Java architect,you should learn these.This page is updated irregularly. Java基础 深入分析 Java SPI 机制和原理 并发编程专题 Executors线程池 线程池ThreadPoolExecutor...
同时,阅读BitSet的源码也是理解其工作原理和潜在问题的关键,这有助于我们更好地利用和优化BitSet在多线程环境下的使用。 最后,文章中可能还介绍了通过博客链接(https://huangyunbin.iteye.com/blog/2194731)...
对于并发编程,文档详细讨论了java.util.concurrent包下的各种并发工具类和接口,如LockSupport、AbstractQueuedSynchronizer、各种锁的实现(ReentrantLock、ReentrantReadWriteLock、StampedLock等)、并发集合...
- 使用`LockSupport.park()`和`LockSupport.unpark()`来精细化控制线程的阻塞和唤醒。 - 尽可能使用无锁编程(如原子变量、并发容器等)和并发工具类,减少锁的使用。 在实际开发中,聪明地使用锁意味着要根据...