LockSupport 详解
      
        
          
          2025-09-15 03:07:06
        
        
              
                
                
                
                  
                    # Technical
                  
                
                
                
                  
                    # JavaConcurrency
                  
                
                
              
          
              
          
      
      为什么 LockSupport 是核心基础类?
写出分别通过 wait/notify 和 LockSupport 的 park/unpark 实现同步?
LockSupport.park() 会释放锁资源吗?那么 Condition.await() 呢?
Thread.sleep()、Object.wait()、Condition.await()、LockSupport.park() 的区别?
如果在 wait() 之前执行了 notify() 会怎样?
如果在 park() 之前执行了 unpark() 会怎样?
LockSupport 用于提供阻塞和唤醒线程的功能。它允许线程在不使用传统的同步机制(如synchronized和ReentrantLock)的情况下被挂起和恢复,适用于实现更复杂的线程控制和等待机制
使用
利用 LockSupport 实现 N 个线程依次打印 1-100
1  | private static volatile int count = 1;  | 
这里不加 continue 会导致?…
属性
1  | public class LockSupport {  | 
构造函数
1  | private LockSupport() {}  | 
LockSupport 只有一个私有的构造函数,说明其无法被实例化
核心方法
1  | // 一直等待,直到获得许可  | 
还有个指定 blocker 的方法
1  | public static void park(Object blocker) {  | 
这个 blocker 参数主要用于诊断目的:
- 帮助识别为什么线程被阻塞
 - 在线程转储中提供更多信息
 - 便于调试复杂的并发问题
 
原理与优势
首先,需要理解两个关键概念:
- 许可:可以把它想象成一种令牌,每个线程最多只有一个许可
 - 计数器:每个线程都有一个与之关联的计数器,用于记录许可的状态
 
park 方法原理
当调用 LockSupport.park() 或 LockSupport.park(Object blocker) 时:
- 首先检查许可的计数器,如果计数器大于 0,则立即返回,并将计数器 -1
 - 如果计数器为 0,则调用操作系统的方法将当前线程置为等待状态(WAITING/TIMED_WAITING)
 - 线程会一直等待,直到以下情况发生之一:a) 其他线程调用了 
LockSupport.unpark(Thread)方法,将该线程作为参数传入;b) 其他线程中断了该线程;c) 等待操作无缘故返回(这种情况被称为「虚假唤醒」,非常罕见) 
unpark 方法原理
- 如果指定线程的许可计数器为 0,则将其设置为 1
 - 如果指定线程当前因 park 操作而被阻塞,则唤醒该线程
 - 如果指定线程当前没有被阻塞,则什么也不做,只是保证下一次 park 操作不会阻塞
 
优势
与传统的 wait/notify 机制相比,有以下几个优势:
- 不需要在同步块中使用
 - park 和 unpark 可以按任意顺序调用,即使 unpark 在 park 之前调用,后续的 park 也不会阻塞
 - 使用起来更加简单,不易出错,不会抛出 
InterruptedException异常 
注意事项
- park 方法不保证线程一定会阻塞。如果在调用 park 之前或者在 park 阻塞期间,有其他线程调用了 unpark,那么 park 可能会立即返回
 - 连续多次调用 unpark 只会累积一个许可