package com.example.foo;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;
public class SomeClass {
static class Outer {
Inner inner = new Inner();
public synchronized String getBoth() {
return this.toString() + " - " + this.inner.toString();
}
class Inner {
public synchronized String getBoth() {
return this.toString() + " - " + Outer.this.toString();
}
@Override
public synchronized String toString() {
Thread.yield(); // To increase risk of deadlock
return "Inner";
}
}
@Override
public synchronized String toString() {
Thread.yield(); // To increase risk of deadlock
return "Outer";
}
}
public static void main(String[] args) throws InterruptedException {
final Outer o = new Outer();
// No problem:
System.out.println(o.getBoth()); // outer, inner
System.out.println(o.inner.getBoth()); // inner, outer
ExecutorService pool = Executors.newFixedThreadPool(4);
for (int i = 0; i < 100; i++) {
pool.execute(() -> {
System.out.println(o.getBoth());
});
pool.execute(() -> {
System.out.println(o.inner.getBoth());
});
}
pool.shutdown();
if (!pool.awaitTermination(10, TimeUnit.SECONDS))
throw new RuntimeException("DEADLOCK!");
System.out.println("END");
}
}
Comments