プログラム悪戦苦闘日記

はてなダイアリーからの移行(遺物)

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以下であればタイムアウトしたことになる。