并发编程专题-基础-16、LockSupport
1. 是什么
是用来创建锁和其他同步类的基本线程阻塞原语
每个使用 LockSupport 的线程都会与一个许可关联,如果该许可可用,并且可在进程中使用,则调用 park() 将会立即返回,否则可能阻塞。如果许可尚不可用,则可以调用 unpark 使其可用
方法:park()、unpark()
2. 等待唤醒
2.1. synchronized
2.1.1. 异常 1
必须在 synchronized 代码块中调用 wait 和 notify,否则报错
2.1.2. 异常 2
必须 t1 先 wait(),然后 t2 再 notify(),否则无法唤醒
2.1.3. 为什么要放在代 synchronized 码块中?⭐️🔴
- wait 和 notify 用来实现多线程之间的协调,wait 表示让线程进入到阻塞状态, notify 表示让阻塞的线程唤醒。
- wait 和 notify 必然是成对出现的,如果一个线程被 wait() 方法阻塞,那么必然需 要另外一个线程通过 notify() 方法来唤醒这个被阻塞的线程,从而实现多线程之间 的通信。
- (如图)在多线程里面,要实现多个线程之间的通信,除了管道流以外,只能通过共享变量的方法来实现,也就是线程 t1 修改共享变量 s,线程 t2 获取修改后的共享变量 s,从而完成数据通信。但是多线程本身具有并行执行的特性,也就是在同一时刻,多个线程可以同时执行。在这种情况下,线程 t2 在访问共享变量 s 之前,必须要知道线程 t1 已经修改过了共享变量 s,否则就需要等待。同时,线程 t1 修改过了共享变量 S 之后,还需要通知在等待中的线程 t2。所以要在这种特性下要去实现线程之间的通信,就必须要通过一个竞争条件去控制线程在什么条件下等待,什么条件下唤醒
- 而 Synchronized 同步关键字就可以实现这样一个互斥条件,也就是在通过共享变 量来实现多个线程通信的场景里面,参与通信的线程必须要竞争到这个共享变量的 锁资源,才有资格对共享变量做修改,修改完成后就释放锁,那么其他的线程就可 以再次来竞争同一个共享变量的锁来获取修改后的数据,从而完成线程之前的通 信。
- 所以这也是为什么 wait/notify 需要放在 Synchronized 同步代码块中的原因,有了 Synchronized 同步锁,就可以实现对多个通信线程之间的互斥,实现条件等待和条件唤醒。
- 另外,为了避免 wait/notify 的错误使用,jdk 强制要求把 wait/notify 写在同步代码块里面,否则会抛出 IllegalMonitorStateException
- 最后,基于 wait/notify 的特性,非常适合实现生产者消费者的模型,比如说用 wait/notify 来实现连接池就绪前的等待与就绪后的唤醒。
2.2. Lock
2.2.1. 异常 1
必须在 lock 和 unlock 中间调用 await() 和 signal(),否则报错
2.2.2. 异常 2
必须 t1 先 await(),然后 t2 再 singal(),否则无法唤醒
2.3. LockSupport
3. 实战经验
4. 参考与感谢
并发编程专题-基础-15、JUC本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议。转载请注明来自 Taylor!
评论