JavaEE初阶——多线程(等待-通知机制:wait-notify)

等待-通知 机制:wait 和 notify

——能够从应用层面上,干预到多个不同线程代码的执行顺序。这里说的干预,不是影响系统的线程调度策略(内核里调度线程,仍然是无需调度)

相当于是在应用程序代码中,让后执行的线程,主动放弃被调度的机会,就可以让先执行的线程,先把对应的代码执行完了。

【用途】
——场景:【线程饿死/线程饥饿】
拿到锁的线程,由于条件不足,无法执行后边的代码,释放锁之后,也参与锁竞争。此时,完全有可能导致,该线程反复获取锁,但是又无法完成实质性的逻辑。其他线程又无法拿到锁。这个情况,就称为:线程饿死/线程饥饿

——可能性:【概率】这种情况出现的概率还是挺高的。
原因:原来拿到锁的线程个,处于RUNNABLE状态;其他线程因为锁冲突出现阻塞,处于BLOCKED状态。原来的线程“近水楼台先得月” ~ ~不用背唤醒,直接就能参与到锁竞争;其他线程需要被唤醒之后,才能参与到锁的竞争。(当然,这里谁能竞争到,也是一个复杂的过程)

——影响:【严重性】是bug,虽然没有死锁那么严重,但是也需要处理。

——解决:【办法:wait 和 notify】
出现这个问题的关键:这个拿到锁的线程,在发现自己要执行的逻辑,不具备前提条件时,应该主动放弃对锁的竞争(主动放弃去CPU上调度执行),进入阻塞。 一直等到,条件具备了(可能是其他线程代码逻辑导致的),此时再解除阻塞,参与锁竞争。
“主动放弃对锁的竞争/主动放弃去CPU上执行”——wait阻塞
“条件具备,解除阻塞”——notify唤醒

——例子:【打印函数】打印函数内部,也是有加锁控制的。
两个线程都要往同一个控制台上打印,如果不加锁控制,也可能会有线程安全问题。比如:打印函数要打印的内容,打印出来的日志,是连续的、完整的,而不是断断续续的出现、混着的。

【原理】
——【wait】
wait的内部做了三件事:

  1. 释放锁
  2. 进入阻塞等待
    由1.2=》其他线程就有机会拿到锁了。
  3. 当其他线程调用notify的时候,wait解除阻塞,并重新获取到锁

wait 和 join 的区别:
join: 等待另一个线程执行完,才继续执行
wait: 等待另一个线程通过notify进行通知(不要求另一个线程执行完)

注意:
wait进入阻塞,只能说明自己释放锁了。是否

你可能感兴趣的:(java-ee)