LockSupport的park与unpark调用顺序验证

本文通过三个实验深入探讨了Java中LockSupport类的unpark和park方法的使用时机与效果,揭示了线程唤醒的机制。实验表明,unpark必须在线程启动后才能生效,无论是在park前还是后调用,都能成功唤醒线程。

1.unpark在thread start之前调用

    public static void main(String[] args) throws InterruptedException{
        Thread thread1 = new Thread(new Runnable() {
            @Override
            public void run() {
                System.out.println("thread1 start");

                try{
                    Thread.sleep(2000);
                } catch (Exception e){
                    e.printStackTrace();
                }

                System.out.println("thread1 run before park");

                LockSupport.park();

                System.out.println("thread1 run after park");
            }
        });
        LockSupport.unpark(thread1);
        thread1.start();

        System.out.println("main thread");

    }

执行结果:

main thread
thread1 start
thread1 run before park

(程序没有退出,线程1一直挂起)

2.unpark在park之前执行

public static void main(String[] args) throws InterruptedException{
        Thread thread1 = new Thread(new Runnable() {
            @Override
            public void run() {
                System.out.println("thread1 start");

                try{
                    Thread.sleep(2000);
                } catch (Exception e){
                    e.printStackTrace();
                }

                System.out.println("thread1 run before park");

                LockSupport.park();

                System.out.println("thread1 run after park");
            }
        });
        thread1.start();
        LockSupport.unpark(thread1);

        System.out.println("main thread");

    }

执行结果:

thread1 start
main thread
thread1 run before park
thread1 run after park

3.unpark在park之后执行

    public static void main(String[] args) throws InterruptedException{
        Thread thread1 = new Thread(new Runnable() {
            @Override
            public void run() {
                System.out.println("thread1 run before park");

                LockSupport.park();

                System.out.println("thread1 run after park");
            }
        });

        thread1.start();

        System.out.println("main thread");
        Thread.sleep(3000);
        LockSupport.unpark(thread1);
    }

执行结果:

main thread
thread1 run before park
thread1 run after park

总结

1.unpark必须在thread start之后才有用,之前调用没有任何效果;

2.thread start之后,unpark在park之前还是之后,作用是一样的,都会重新唤醒线程;

Java 中的 `LockSupport.unpark` 是用于线程阻塞唤醒机制的关键工具之一,它属于 `java.util.concurrent.locks` 包的一部分,底层由 `sun.misc.Unsafe` 提供支持。`unpark` 通常 `park` 方法成对使用,用于实现更灵活的线程控制逻辑,尤其在构建高级并发工具(如 `ReentrantLock`、`Condition`、线程池等)时非常关键。 ### 线程唤醒机制 `LockSupport.unpark(Thread thread)` 的作用是允许指定线程继续执行,即解除其阻塞状态。如果目标线程尚未调用 `park` 或者已经调用了 `park` 但尚未阻塞,则该线程在后续调用 `park` 时不会被阻塞。这种机制类似于信号量,但它是线程级别的,且具有更轻量级的特性。 ```java Thread t = new Thread(() -> { System.out.println("Before park"); LockSupport.park(); System.out.println("After park"); }); t.start(); // 确保线程已经启动 try { Thread.sleep(1000); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println("Unparking thread"); LockSupport.unpark(t); ``` 在上述示例中,主线程调用 `LockSupport.unpark(t)` 唤醒线程 `t`,使其从 `park()` 调用中返回并继续执行。 ### Object.wait/notify 的区别 传统的 `Object.wait()` 和 `Object.notify()` 不同,`LockSupport.park()` 和 `LockSupport.unpark()` 不依赖于对象的监视器锁,而是直接作用于线程。这意味着它们可以在不持有锁的情况下使用,避免了因调用 `wait()` 而必须持有锁的问题,提高了并发编程的灵活性。 ### AQS 中的应用 在 AQS(AbstractQueuedSynchronizer)中,`unpark` 被广泛用于线程调度。例如,在 `release` 方法中,当一个线程释放同步状态后,AQS 会通过 `unparkSuccessor` 方法唤醒队列中的下一个节点所对应的线程,确保同步状态的释放能够传播到后续等待的线程[^1]。 ```java public final boolean release(int arg) { if (tryRelease(arg)) { Node h = head; if (h != null && h.waitStatus != 0) unparkSuccessor(h); return true; } return false; } ``` 在这个过程中,`unparkSuccessor` 会找到下一个需要唤醒的节点,并调用 `LockSupport.unpark(node.thread)` 来唤醒该线程。这种机制确保了线程间的高效协作,同时避免了不必要的竞争和阻塞。 ### 注意事项 尽管 `LockSupport.unpark` 提供了强大的线程控制能力,但在使用时仍需注意以下几点: - **线程生命周期**:确保调用 `unpark` 时目标线程仍然存活,否则调用无效。 - **调用顺序**:`unpark` 可以于 `park` 调用,此时 `park` 不会阻塞线程,而是直接返回。但如果 `unpark` 在 `park` 之后调用,则线程会一直阻塞直到再次调用 `unpark`。 - **资源竞争**:虽然 `LockSupport` 提供了较低层次的线程控制,但在复杂并发场景下仍需谨慎处理线程间的协调问题,以避免死锁或活锁。 ### 总结 `LockSupport.unpark` 是 Java 并发编程中用于线程唤醒的重要工具,它提供了比传统 `wait/notify` 更加灵活的线程控制方式。在 AQS 等高级并发组件中,`unpark` 被广泛用于实现高效的线程调度机制,确保同步状态的正确传播。 ---
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值