torutkのブログ

ソフトウェア・エンジニアのブログ

Java try-finally文

Java Threads を読んでいて、明示的なロックの使用例において、以下のようなtry-finally文を使っていました。

    Lock scoreLock = new ReentrantLock();
    ...
    void doSomething() {
        try {
            scoreLock.lock();
            // 同期が必要な処理
        } finally {
            scoreLock.unlock();
        }
    } 

try文の中で、実行時例外が投擲されたりreturn文を書いた場合でも、finally文が必ず実行されます。これを以下のように記述すると、NGです。

    void doSomething() {
        scoreLock.lock();
        // 同期が必要な処理
        scoreLock.unlock();
    }

処理の中で例外が発生すると、ロックが解放されず、デッドロックを引き起こします。

C++言語では、RAII(Resource Aquision Is Initialization)と呼ばれるイディオムがこの役割に相当します。

template <typename T>
class locker {
public:
    locker(T* p) : pLock(p) { pLock->lock(); }
    ~locker() { pLock->unlock(); }
private:
    T* pLock;
};

void doSomething() {
    locker theLocker(someLock);
    // 同期が必要な処理
}

まあ、C++の場合は例外等の中断が発生しない場合でも、メソッドから抜けるまでロックを獲得し続けるのでRAIIをロックに使用するのはあまりよい方法ではないかもしれません。