ReentrantLockの質問です
4287 ワード
今日javaの同時プログラミングを振り返る時に1つの問題に出会って、少し奇妙なコードは以下の通りです
BlockMutexはコンカレントの問題が発生する可能性のあるリソースなので、lockを使用して同期を実現します.このオブジェクトを作成するスレッドは、コンストラクタなどのオブジェクトロックを作成するときに、f()メソッドを実行するときにロックを申請します.
これはTask taskが初期化されると、そのtaskはロックを持ち、taskがrunメソッドを実行するとf()関数が実行される.BlockThreadはBlockMutexを初期化するとBlockMutexのオブジェクトロックを持ち、ReentrantLockは再読み込みをサポートするので、BlockThreadはf()メソッドを実行し続けるべきである
main関数でのテスト実行結果は次のとおりです.
不思議なことに、blockThreadスレッドは実行時にf()メソッドの中でずっとブロックされていて、BlockThreadはすでにBlockMutexのオブジェクトロックを持っていて、ロックを申請し続けるべきではありません.しばらく考えた結果、blockThreadスレッドはBlockMutexのオブジェクトロックを持っていないことが分かりました.blockThread初期化はメインスレッドで行われ、ロックの申請はコンストラクタで完了するので、BlockMutexを持っているオブジェクトロックはメインスレッドです.この考えを検証するために、メインスレッドにf()メソッドを実行させ、実行成功を待つことがなければ、私たちの考えは成立し、main関数を変更することは以下のようになります.
実行結果
予想が成り立つ
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
予想が成り立つ