Java 中 sleep() 和 wait() 方法关于锁的对比实验

我们知道,在 Java 中,通过 Thread.sleep() 和 Object 的 wait 方法都可以阻塞当前线程的执行。但由于sleep() 不会释放锁对象,而 wait()会释放锁对象,因此在多线程并发的环境中,它们的效果,是截然不同的。并且,用法上也有一定区别:sleep 阻塞时间到了以后,会自动继续往下执行;但使用 wait 时,则必须使用 notify 或 notifyAll 来唤醒。下面通过一段实验代码来验证记录:

public class SleepAndWait {

    public static void main(String[] args) {
        SleepAndWait sleepAndWait = new SleepAndWait();
        new Thread(() -> {
            sleepAndWait.sleepOrWait();
        }).start();
        new Thread(() -> {
            sleepAndWait.func();
        }).start();
    }

    private void sleepOrWait() {
        synchronized (this) {
            System.out.println("1. before block");
            try {
                // 1. 验证 sleep 不会释放锁
                Thread.sleep(500);

                // 2. 验证 wait 会释放锁
                // 因为 wait 释放了锁,所以并发时 func 会立即得到执行
//                this.wait();
                System.out.println("3. after block");
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }

    private void func() {
        synchronized (this) {
            System.out.println("2. call func");
            this.notify();
        }
    }
}

首先我们使用 sleep() 进行阻塞,结果输出:

1. before block
3. after block
2. call func

说明:因为 sleepOrWaitfunc 分别由不同的线程执行,但是他们的 synchronized 使用了同一个锁对象,而且因为 sleep() 方法不会释放对象锁,所以能保证并发时是按顺序先执行完了 sleepOrWait 同步块内的所有代码,然后 func 中的同步块才会被执行,所以顺序是 1 -> 3 ->2。

然后我们修改由 wait() 进行阻塞,结果将输出:

1. before block
2. call func
3. after block

说明:因为 wait() 方法会释放当前的锁对象,所以虽然 sleepOrWait 同步块内的 wait() 方法后还有语句未执行,但是由于 wait() 的阻塞作用,并且已经释放了锁对象,所以 func 中被阻塞的同步块获得锁对象开始执行,并且通过调用同一个对象的 notify 方法,唤醒执行 sleepOrWait 的线程继续执行,故输出顺序是1 -> 2 -> 3。
如果 wait 没有释放锁对象这一特性,那么就只会输出1了,2和3将永远得不到执行。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值