package com.java;
import java.lang.reflect.Field;
import sun.misc.Unsafe;
class SynTestClass {
protected Thread mainThread;
public SynTestClass(Thread mainThread) {
this.mainThread = mainThread;
}
public void t() {
System.out.println(Thread.currentThread().getName() + ": t");
synchronized(mainThread) {
mainThread.notify();
System.out.println("notified");
}
try {
Thread.sleep(24 * 60 * 60 * 1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
public synchronized void tt() {
System.out.println(Thread.currentThread().getName() + ": tt");
synchronized(mainThread) {
mainThread.notify();
System.out.println("notified");
}
try {
Thread.sleep(24 * 60 * 60 * 1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
class SynTestClass2 extends SynTestClass {
public SynTestClass2(Thread mainThread) {
super(mainThread);
}
}
class ThreadTest1 extends Thread {
private SynTestClass st;
public ThreadTest1(SynTestClass st) {
this.st = st;
}
public void run() {
st.t();
}
}
class ThreadTest11 extends Thread {
private SynTestClass st;
public ThreadTest11(SynTestClass st) {
this.st = st;
}
public void run() {
st.tt();
}
}
class ThreadTest2 extends Thread {
private SynTestClass2 st;
public ThreadTest2(SynTestClass2 st) {
this.st = st;
}
public void run() {
st.t();
}
}
class ThreadTest22 extends Thread {
private SynTestClass2 st;
public ThreadTest22(SynTestClass2 st) {
this.st = st;
}
public void run() {
st.tt();
}
}
public class SynchronizedTest {
public static Unsafe getUnsafe() throws Throwable {
Class<?> unsafeClass = Unsafe.class;
for (Field f : unsafeClass.getDeclaredFields()) {
if ("theUnsafe".equals(f.getName())) {
f.setAccessible(true);
return (Unsafe) f.get(null);
}
}
throw new IllegalAccessException("no declared field: theUnsafe");
}
public static void main(String[] args) {
Thread mainThread = Thread.currentThread();
SynTestClass2 st2 = new SynTestClass2(mainThread);
Thread t = new ThreadTest2(st2);
// Thread t = new ThreadTest22(st2);
t.start();
try {
synchronized(mainThread) {
mainThread.wait();
}
} catch (InterruptedException e) {
System.out.println("Ok: it's expected, main thread continue to run...");
}
Unsafe unsafe = null;
try {
unsafe = SynchronizedTest.getUnsafe();
} catch (Throwable e) {
e.printStackTrace();
}
boolean ok = unsafe.tryMonitorEnter(st2);
if (ok) {
st2.t();
// st2.tt();
unsafe.monitorExit(st2);
} else {
System.out.println(Thread.currentThread().getName() + ": fail to enter monitor");
}
}
}