并发编程笔记二:wait/notify原理、join原理、park/unpark原理

wait/notify原理

wait/notify是本地方法,不是jdk实现的,所以看不到它的源码。
在这里插入图片描述
wait/notify是基于synchronized的,所以先介绍synchronized,synchronized修饰到对象之后,锁对象会关联一个Moniror对象:

  • WaitSet是等待队列,当前线程获取到锁对象后调用wait方法后会进入该WaitSet等待队列。
  • EntryList是阻塞队列,当前线程获取不到该锁对象会进入该EntryList阻塞队列。
  • Owner,当前线程获取到锁对象,并正常执行。

wait/notify原理:

  • 就是当前线程前线程进入WaitSet等待队列,状态由Runnable–>Waiting,即调用了wait()。
  • 接着当前线程可以去竞争锁,竞争成功则去运行;竞争失败后进入EntryList阻塞队列,状态由WaiTing–>Runnable或者WaiTing–>Runnable–>Blocked,即调用notify()/notifyall()后,被notify的线程会从WaitSet等待队列里面出来。

join原理

底层使用的是保护性暂停模式,对join的线程对象底层调用的isAlive()和wait()方法。
部分源码:

  • 最简单的join()调用。
 public final void join() throws InterruptedException {
        join(0);
    }
  • join(0)调用。
public final synchronized void join(long millis)
    throws InterruptedException {
        long base = System.currentTimeMillis();
        long now = 0;

        if (millis < 0) {
            throw new IllegalArgumentException("timeout value is negative");
        }

        if (millis == 0) {
            while (isAlive()) {
                wait(0);
            }
        } else {
            while (isAlive()) {
                long delay = millis - now;
                if (delay <= 0) {
                    break;
                }
                wait(delay);
                now = System.currentTimeMillis() - base;
            }
        }
    }

join原理:

  • 说白了就是不停地使用isAlive()去判断当前线程是否还是存活,存活则让监控线程随着while循环阻塞在此,结束则跳出循环,监控线程往下运行。简单来说就是使用while阻塞监控线程 。
  • isAlive()是一个本地方法,判断当前线程是否还存活。使用wait()是为了降低对cpu的使用率。

park/unpark原理

LockSupport.park()和LockSupport.unpark(Thread thread)是本地方法,不是jdk实现的,所以看不到它的源码。
park/unpark原理:

  • 每个线程都有自己的一个 Parker 对象,由三部分组成 _counter , _cond (条件)和 _mutex (互斥量)。
  • 当调用park时,先尝试能否直接拿到“许可”,即_counter>0时,如果成功,则把_counter设置为0,并返回。
  • 当unpark时,直接设置_counter为1,再unlock mutex返回。如果_counter之前的值是0,则还要调用pthread_cond_signal唤醒在park中等待的线程。

使用小故事去理解:

线程就像一个旅人,Parker 就像他随身携带的背包,条件变量就好比背包中的帐篷。_counter 就好比背包中的备用干粮(0 为耗尽,1 为充足)
调用 park 就是要看需不需要停下来歇息
如果备用干粮耗尽,那么钻进帐篷歇息
如果备用干粮充足,那么不需停留,继续前进
调用 unpark,就好比令干粮充足
如果这时线程还在帐篷,就唤醒让他继续前进
如果这时线程还在运行,那么下次他调用 park 时,仅是消耗掉备用干粮,不需停留继续前进
因为背包空间有限,多次调用 unpark 仅会补充一份备用干粮s

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值