Tiger Concurrency Utilities
まずは同期オブジェクトから。
Lockインターフェイス - ミューテックス
1.sychronizedの違い
synchronizedはオブジェクト全体にロックがかかるが、LockはLockオブジェクトにロックがかかる。
2.ロックのしかた
・普通にロックするときは、Lock#lock()を呼ぶ。ロック解除はLock#unlock()。
Lock#unlock()を確実に呼ぶためにfinally節内で呼ぶのはお約束。
・あるのスレッドがロックを取得しているときに、別のスレッドがロックを取得しようとすると、待たされる。
・Lock#lockInterruptibly()は、Lock#lock()と同様にロックを取得されていると待たされるが、
Thread#interrupt()が呼ばれると、InterruptedExceptionをthrowする。
・Lock#tryLock()は、ロックが取得されていると待たずにfalseを返す。
3.ReentranceLock(再入可能ロック)とは?
Lockを取得したスレッドが、同一のLockオブジェクトのロックを取得しようとしたとき、何度でも取得できるロックのこと。
もし同一のロックが取得でいないと、自分自身でデッドロックを引き起こす。
ちなみに、synchronizedキーワードはreentrance(再入可能)である。
Conditionインターフェイス
1.概要
Lock#newCondition()で生成する。基本的には、Object#wait(), Object#notify()/notifyAll()と同じらしい。対応関係はおおよそ、
Object#wait() (引数なし) → Condition#await() (引数なし) Object#wait() (引数つき) → Condition#await() (引数つき) Object#notify() → Condition#signal() Object#notifyAll() → Condition#signalAll()
といったところか。Object系のメソッドよりこちらがいいのはLockオブジェクトの必要性が明示できるからだと思う。
Object系メソッドはsynchronizedの中で呼ばないと例外がでるが、ConditionはLockがないと作れないので、そもそもこんな心配は要らない。
2.Conditionのメソッド達
Object系のメソッドより便利なものがいくつか追加されている。
await() (引数なし) いわゆるObject#wait() interrupt()を呼ばれるかsignal()/singnalAll()で再開する。 await(long, TimeUnit) タイムアウトつきawait() Object#wait()との違いは、タイムアウトしたのかsignal()/signalAll()で再開したのかが区別がつくということ awaitUntil(Date) 期限付きawait() awaitUninterruptibity() inerrupt()呼ばれても中断しないawait() signal()/singalAll() await()しているやつを起こす
Condition#await(long, TimeUnit)は、戻り値が「推定残り待ち時間(ナノ秒)」であるので、0以下であればタイムアウトしたことになる。