// Not really how java.util.concurrent.Semaphore is implemented
@ThreadSafe
public class SemaphoreOnLock {
private final Lock lock = new ReentrantLock();
// CONDITION PREDICATE: permitsAvailable (permits > 0)
private final Condition permitsAvailable = lock.newCondition();
@GuardedBy("lock") private int permits;
SemaphoreOnLock(int initialPermits) {
lock.lock();
try {
permits = initialPermits;
} finally {
lock.unlock();
}
}
/* other code omitted.... */
Java Concurrency in Practiceリスト 14.12 Lock を使用して実装されたセマフォのカウントから抽出された上記のサンプルについて質問があります。
なぜコンストラクターでロックを取得する必要があるのか 疑問に思っています(lock.lock()が呼び出されるように)。私の知る限り、コンストラクターはアトミックです(エスケープされた参照を除く)。他のスレッドは参照を取得できないため、半分構築されたオブジェクトは他のスレッドから見えません。したがって、コンストラクターの synchronized 修飾子は必要ありません。さらに、オブジェクトが安全に公開されている限り、メモリの可視性についても心配する必要はありません。
では、なぜコンストラクター内で ReentrantLock オブジェクトを取得する必要があるのでしょうか。