BlockingQueueメモ
前回の記事で@kaoriyaさんに教えてもらったBlockingQueueについて。
notify()/wait()にしてもLock/Conditionのsignal()/await()にしても、待つ前に通知されてしまうと通知を取り逃がしてしまう問題がある。
そこでBlockingQueueを同期化のためのオブジェクトとして使う。
これによって
- 通知を取り逃がしてしまう事なく
- Spurious Wakeupを意識する事もなく?(要出展)
スレッド間の同期を行う事ができる。
また、当然キューなので、Producer/Consumerが1対1でない場合にも使える。
特にBlockingQueueの中でもSynchronousBlockingQueueはGoのchannelのように使えて大変便利。
notify()/wait()とBlockingQueueによる同期はUDPとTCPの違いに似てるかも。
かたや投げっぱなし、かたや必ず通知を受け取り、Spurious Wakeupの影響も受けないとすれば内部的にTCPみたいにちゃんとリトライ*1も行っているんじゃないだろうか(あくまで予想)。
気になること
- 各BlockingQueueの実装(及び各JDKによる実装)においてどれぐらい速度差があるのか
- BlockingQueueはSpurious Wakeupの影響は本当に受けないのか(実装による気がしていて、おそらく仕様としては含まれていない)
Spurious Wakeupについて
@tyru Spurious Wakeupたぶん対策されているはず。それが生じうるのはデータを取り出す/入れるという操作なんだけど、成功したように見えて実は失敗してましただとメソッドの意味がまったくなくなってしまうので。ちなみに実際のロックはLockSupport使ってました。
— MURAOKA Taro (@kaoriya) 2015, 3月 23
とのことです。
*1:実際は単なるループでのチェック