Slide 22
Slide 22 text
$ java VirtualThreadDeadlockExample.java
import java.time.Duration;
import java.util.List;
import java.util.concurrent.locks.ReentrantLock;
import java.util.stream.IntStream;
import java.util.stream.Stream;
public class VirtualThreadDeadlockExample {
public static void main(String[] args) {
// Fairness lock
。待機リストの先頭から順番に獲得する
final ReentrantLock lock = new ReentrantLock(true);
//
メインスレッドがロック取得
System.out.println(Thread.currentThread() + " took lock");
lock.lock();
//
ロック取得メソッド
Runnable takeLock = () -> {
try {
System.out.println(Thread.currentThread() + " waiting for lock");
lock.lock();
System.out.println(Thread.currentThread() + " took lock");
Thread.sleep(100);
} catch (InterruptedException _) {
} finally {
lock.unlock();
System.out.println(Thread.currentThread() + " released lock");
}
};
// `synchronized`
ブロック *
外*
から獲得 = Unpinned Thread
。待機リストの先頭に
Thread unpinnedThread = Thread.ofVirtual().name("unpinned").start(takeLock);
// `synchronized`
ブロック *
内*
から獲得を繰り返し、利用可能なPlatform Thread
全てでPinning
List pinnedThreads = IntStream.range(0, Runtime.getRuntime().availableProcessors())
.mapToObj(i -> Thread.ofVirtual().name("pinning-" + i).start(() -> {
synchronized (new Object()) {
takeLock.run();
}
})).toList();
//
メインスレッドがロック解放
try {
Thread.sleep(500);
} catch (InterruptedException _) {}
System.out.println(Thread.currentThread() + " released lock");
lock.unlock();
//
しかしUnpinned Thread
を動かせるPT
が存在しないのでロックが獲得できずDeadLock
System.out.println("Waiting for taking lock");
Stream.concat(Stream.of(unpinnedThread), pinnedThreads.stream()).forEach(thread -> {
try {
if (!thread.join(Duration.ofSeconds(5))) {
System.out.println("Deadlock detected");
}
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
});
}
}
22