16 线程休息室-waitset

概述

当前线执行的执行的时候,遇到了wait方法,就会释放锁,进入阻塞状态,这个线程就会被放到waitset存起来,
其实这个waitset是不存在的一个数据结构,只是方便理解,有些人就提出了这么个概念

java 官方的一个描述(wait方法)
This method causes the current thread (call it T) to place itself in the wait set for this object and then to relinquish any and all synchronization claims on this object.

wait set几点说明
  1. 所有对象都会由有个wait set,用来存放该对象wait方法之后的进入block状态的线程
  2. 线程被notify之后,不一定立即执行,需要抢锁
  3. 线程从wait set被唤醒的顺序不一定是FIFO
  4. 线程被唤醒后,必须重新获取锁,但是并不是从获取锁的地方执行,而是从wait的地方开始执行,也就说jvm会记录每个线程wait的位置

测试:线程从wait set被唤醒的顺序不一定是FIFO

package study.wyy.concurrency.thread.waitset;

import lombok.extern.slf4j.Slf4j;

import java.util.stream.IntStream;

/**
 * @author :wyaoyao
 * @date : 2020-04-11 10:10
 */
@Slf4j
public class Test1 {

    // 定义一个锁
    private static final Object LOCK = new Object();

    public static void main(String[] args) throws InterruptedException {
        // 模拟9个线程,进行wait
        IntStream.rangeClosed(1, 9).forEach(i ->
            new Thread(String.valueOf(i)) {
                @Override
                public void run() {
                    synchronized (LOCK){
                        try {
                            log.info("{} will place to wait set",Thread.currentThread().getName());
                            LOCK.wait();
                            log.info("{} will leave off wait set",Thread.currentThread().getName());
                        } catch (InterruptedException e) {
                            e.printStackTrace();
                        }
                    }

                }
            }.start());

        // 休眠一会,进行唤醒
        Thread.sleep(3000);

        IntStream.rangeClosed(1,10).forEach(i->{
            synchronized (LOCK){
                LOCK.notify();
                try {
                    Thread.sleep(300);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        });
    }
}

日志输出

[1] INFO study.wyy.concurrency.thread.waitset.Test1 - 1 will place to wait set
[7] INFO study.wyy.concurrency.thread.waitset.Test1 - 7 will place to wait set
[6] INFO study.wyy.concurrency.thread.waitset.Test1 - 6 will place to wait set
[5] INFO study.wyy.concurrency.thread.waitset.Test1 - 5 will place to wait set
[4] INFO study.wyy.concurrency.thread.waitset.Test1 - 4 will place to wait set
[3] INFO study.wyy.concurrency.thread.waitset.Test1 - 3 will place to wait set
[2] INFO study.wyy.concurrency.thread.waitset.Test1 - 2 will place to wait set
[9] INFO study.wyy.concurrency.thread.waitset.Test1 - 9 will place to wait set
[8] INFO study.wyy.concurrency.thread.waitset.Test1 - 8 will place to wait set
[1] INFO study.wyy.concurrency.thread.waitset.Test1 - 1 will leave off wait set
[6] INFO study.wyy.concurrency.thread.waitset.Test1 - 6 will leave off wait set
[7] INFO study.wyy.concurrency.thread.waitset.Test1 - 7 will leave off wait set
[8] INFO study.wyy.concurrency.thread.waitset.Test1 - 8 will leave off wait set
[9] INFO study.wyy.concurrency.thread.waitset.Test1 - 9 will leave off wait set
[2] INFO study.wyy.concurrency.thread.waitset.Test1 - 2 will leave off wait set
[3] INFO study.wyy.concurrency.thread.waitset.Test1 - 3 will leave off wait set
[4] INFO study.wyy.concurrency.thread.waitset.Test1 - 4 will leave off wait set
[5] INFO study.wyy.concurrency.thread.waitset.Test1 - 5 will leave off wait set

会发现不是先进先出的顺序

测试:

package study.wyy.concurrency.thread.waitset;

import lombok.extern.slf4j.Slf4j;

/**
 * @author :wyaoyao
 * @date : 2020-04-11 10:21
 */
@Slf4j
public class Test2 {
    // 定义一个锁
    private static final Object LOCK = new Object();

    private static void work(){
       
        synchronized (LOCK){
         log.info("begining ......");
            try {
                log.info("Thread will coming");
                LOCK.wait();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
        log.info("Thread will out");
    }

    public static void main(String[] args) throws InterruptedException {
        new Thread(()->{
            work();
        }).start();
        Thread.sleep(1000);
        synchronized (LOCK){
            LOCK.notify();
        }
    }
}

[Thread-0] INFO study.wyy.concurrency.thread.waitset.Test2 - begining ......
[Thread-0] INFO study.wyy.concurrency.thread.waitset.Test2 - Thread will coming
[Thread-0] INFO study.wyy.concurrency.thread.waitset.Test2 - Thread will out

可见线程wait唤醒之后,虽然会去抢锁执行,但是执行的时候,还是会从wait的地方开始执行,没有再次打印
begining …

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值