スレッドのロック
2007/03/30 (Fri) 22:07:46 JST
WebObjectsには、Javaの仕様とは別にマルチスレッドを制御するクラスが用意されています。NSLockingがそのインターフェースで、ロック可能なクラスには lock()
, unlock()
のメソッドが実装されています。EOObjectStore とそのサブクラス、EOObjectStoreCoordinator, EODatabaseContext, EOEditingContext がロック可能です。
ロック可能なオブジェクトの管理
WebObjectsが用意するロック可能なオブジェクトは、適当なタイミングでロックがかけられます。EOEditingContext など自前でオブジェクトを作る場合は自分でロックを管理する必要があります。
?NSRecursiveLock
lock()
, unlock()
の実装で主に使われているのは ?NSRecursiveLock 、いわゆるモニタです。lock()
を呼んだスレッドのみが、 unlock()
するまでオブジェクトを操作する権限を持ちます。ロックされている状態で他のスレッドからそのオブジェクトをロックしようとすると、ロックが解除されるまで待ちます。ロックが解除されなければ延々と待ち続け、どのスレッドからもオブジェクトを操作できなくなる状態、デッドロックとなります。
注意点
lock(), unlock() の順序と回数を守る
オブジェクトは何度でも lock()
できますが、順序と回数を守らないとデッドロックになります。
- 何度も
lock()
する場合、連続してlock()
する -
lock()
した回数だけ連続してunlock()
する
簡単な話が、 lock()
, ..., lock()
, unlock()
, ..., unlock()
と実行しなければならない、ということです。
lock() した瞬間にスレッドがブロックされるわけではない
lock()
したオブジェクトが他のスレッドから lock()
されない限り、どのスレッドも止まりません。?NSRecursiveLock の目的はスレッドにオブジェクトの操作権限を与えることで、他のスレッドを待たせることではありません。
例えば EOEditingContext を生成しても、他のスレッドと共有していて、さらに他のスレッドが lock()
しようとしない限り、 lock()
したまま捨てても何の問題もありません。
Inverse Pages: オブジェクトのロック ロックについて オブジェクトストアのロック