多线程的 waitset

多线程的waitset介绍

waitset 在线程wait()方法执行后,会被放入被锁对象的一个waitset里面去,而当前wait()的位置也会被记录。

 private final static Object object = new Object();


        IntStream.rangeClosed(1, 10).forEach(s -> {
            new Thread(() -> {
                synchronized (object) {
                    System.out.println(Thread.currentThread().getName() + " --- > will wait ....");
                    try {
                        object.wait();
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }

                    System.out.println(Thread.currentThread().getName() + " --- > will leave ....");

                }
            }).start();
        });


        try {
            Thread.sleep(4_000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }


        IntStream.rangeClosed(1, 10).forEach(s -> {
            new Thread(() -> {
                synchronized (object) {

                    object.notify();

                    try {
                        Thread.sleep(1000);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }

                }

            }).start();
        });


    }

验证线程从wait set中被唤醒的顺序不一定是FIFO

Thread-1 --- > will wait ....
Thread-0 --- > will wait ....
Thread-8 --- > will wait ....
Thread-5 --- > will wait ....
Thread-9 --- > will wait ....
Thread-4 --- > will wait ....
Thread-2 --- > will wait ....
Thread-3 --- > will wait ....
Thread-7 --- > will wait ....
Thread-6 --- > will wait ....
Thread-1 --- > will leave ....
Thread-6 --- > will leave ....
Thread-7 --- > will leave ....
Thread-3 --- > will leave ....
Thread-2 --- > will leave ....
Thread-4 --- > will leave ....
Thread-9 --- > will leave ....
Thread-5 --- > will leave ....
Thread-8 --- > will leave ....
Thread-0 --- > will leave ....

线程被唤醒后,必须重新去获取锁,会记录之前wait的位置,在wait的位置继续往下执行


    private final static Object object = new Object();

    void work() {

        synchronized (object) {

            System.out.println(" 开始执行 work ");

            try {
                object.wait();  //此处等待后,再次回唤醒后继续从当前位置执行。
                System.out.println(" wait 。。。");
            } catch (InterruptedException e) {
                e.printStackTrace();
            }

            System.out.println(" 结束执行 work ");
        }


    }

结果

 开始执行 wait 
 wait 。。。
 结束执行 wait 

结论

1、所有的对象都会有一个wait set,用来存放调用了该对象的wait方法之后进入block状态的线程

2、wait() 调用者是Lock对象,是释放锁的;sleep() 调用者是线程自己,但不释放锁。

3、线程被notify唤醒后,不一定立即执行。

​ 唤醒顺序不是FIFO。

​ 当线程重新获得锁后,也不会从头开始执行,而是从wait处之后的代码开始继续执行(执行地址恢复)。

发布了241 篇原创文章 · 获赞 66 · 访问量 13万+

猜你喜欢

转载自blog.csdn.net/weixin_38361347/article/details/103980730