ReentrantLockの質問です

4287 ワード

今日javaの同時プログラミングを振り返る時に1つの問題に出会って、少し奇妙なコードは以下の通りです
class BlockMutex {
    private Lock lock = new ReentrantLock();

    public BlockMutex() {
        lock.lock();
    }

    public void f(String name) {
        lock.lock();
        System.out.println(name+" lock acquired in f() ");
    }

}

BlockMutexはコンカレントの問題が発生する可能性のあるリソースなので、lockを使用して同期を実現します.このオブジェクトを作成するスレッドは、コンストラクタなどのオブジェクトロックを作成するときに、f()メソッドを実行するときにロックを申請します.
class BlockThread implements Runnable {
    // BlockThread blockMutex 
    private BlockMutex blockMutex = new BlockMutex();

    public BlockMutex getBlockMutex() {
        return blockMutex;
    }

    @Override
    public void run() {
        System.out.println("waiting lock in f()");
        blockMutex.f("BlockThread");
        System.out.println("broken out of blocked call");
    }
}

これはTask taskが初期化されると、そのtaskはロックを持ち、taskがrunメソッドを実行するとf()関数が実行される.BlockThreadはBlockMutexを初期化するとBlockMutexのオブジェクトロックを持ち、ReentrantLockは再読み込みをサポートするので、BlockThreadはf()メソッドを実行し続けるべきである
public static void main(String[] args) throws InterruptedException {
        BlockThread blockThread=new BlockThread();
        Thread thread = new Thread(blockThread);
        thread.start();
        TimeUnit.SECONDS.sleep(1);
        System.out.println("main has finished ");
    }

main関数でのテスト実行結果は次のとおりです.
waiting lock in f()
main has finished 

不思議なことに、blockThreadスレッドは実行時にf()メソッドの中でずっとブロックされていて、BlockThreadはすでにBlockMutexのオブジェクトロックを持っていて、ロックを申請し続けるべきではありません.しばらく考えた結果、blockThreadスレッドはBlockMutexのオブジェクトロックを持っていないことが分かりました.blockThread初期化はメインスレッドで行われ、ロックの申請はコンストラクタで完了するので、BlockMutexを持っているオブジェクトロックはメインスレッドです.この考えを検証するために、メインスレッドにf()メソッドを実行させ、実行成功を待つことがなければ、私たちの考えは成立し、main関数を変更することは以下のようになります.
public class LockInterruptTest {

    public static void main(String[] args) throws InterruptedException {
        BlockThread blockThread=new BlockThread();
        Thread thread = new Thread(blockThread);
        blockThread.getBlockMutex().f("main");
        thread.start();
        TimeUnit.SECONDS.sleep(1);
        System.out.println("main has finished ");
    }

}

実行結果
main lock acquired in f() 
waiting lock in f()
main has finished 

予想が成り立つ