The following program causes the thread executing main() to end up with an
incorrect priority. It starts as 5, and after all the priority inversion is finished,
it is priority 6. Use ^\\ to view the priority when prompted to do so.
class A {
}
class runner extends Thread {
A desiredObject;
runner(A initDesiredObject) {
desiredObject = initDesiredObject;
}
public void run() {
System.err.println(this + ": trying to aquire");
synchronized (desiredObject) {
System.err.println(this + ": got it");
System.err.println(this + ": releasing");
}
}
}
public class priotest {
static A desiredObject1;
static A desiredObject2;
public static void main(String args[]) {
desiredObject1 = new A();
desiredObject2 = new A();
Thread t1 = new runner(desiredObject1);
Thread t2 = new runner(desiredObject2);
t1.setPriority(6);
t2.setPriority(7);
Thread.currentThread().setPriority(5);
synchronized (desiredObject2) {
synchronized (desiredObject1) {
System.err.println(Thread.currentThread() +
": starting threads");
t1.start();
t2.start();
try {
Thread.sleep(5 * 1000);
} catch (InterruptedException ex) {
}
System.err.println(Thread.currentThread() +
": releasing desiredObjects");
}
}
synchronized (desiredObject1) {
synchronized (desiredObject2) {
}
}
System.err.println(Thread.currentThread() + ": hit ^\\\\ now");
try {
Thread.sleep(5 * 1000);
} catch (InterruptedException ex) {
}
}
}
Here is a sample run:
tsukune % java priotest
Thread[main,5,main]: starting threads
Thread[Thread-4,6,main]: trying to aquire
Thread[Thread-5,7,main]: trying to aquire
Thread[main,5,main]: releasing desiredObjects
Thread[Thread-4,6,main]: got it
Thread[Thread-4,6,main]: releasing
Thread[Thread-5,7,main]: got it
Thread[Thread-5,7,main]: releasing
Thread[main,5,main]: hit ^\\ now
SIGQUIT 3* quit
Full thread dump:
"Finalizer thread" (TID:0xee300358, sys_thread_t:0xef490de8) prio=1
"Async Garbage Collector" (TID:0xee300308, sys_thread_t:0xef4c0de8) prio=1
"Idle thread" (TID:0xee300290, sys_thread_t:0xef4f0de8) prio=0 *current thread*
"clock handler" (TID:0xee300098, sys_thread_t:0xef5b0de8) prio=11
"main" (TID:0xee300048, sys_thread_t:0x7cb70) prio=6
priotest.main(priotest.java:61)
Monitor Cache Dump:
unknown key (key=0xef4c0de8): unowned
Waiting to be notified:
"Async Garbage Collector"
unknown key (key=0x7cb70): unowned
Waiting to be notified:
"main"
Registered Monitor Dump:
Finalize me queue lock: unowned
Waiting to be notified:
"Finalizer thread"
Thread queue lock: unowned
Class lock: unowned
Java stack lock: unowned
Code rewrite lock: unowned
Heap lock: unowned
Has finalization queue lock: unowned
Monitor IO lock: unowned
Child death monitor: unowned
Event monitor: unowned
I/O monitor: unowned
Alarm monitor: unowned
Waiting to be notified:
"clock handler"
Sbrk lock: unowned
Monitor cache lock: unowned
Monitor registry: monitor owner: "Idle thread"
Thread Alarm Q:
sys_thread_t 0xef4c0de8 [Timeout in 997 ms]
sys_thread_t 0x7cb70 [Timeout in 3932 ms]
This is happening because green threads stores the correct thread priority
in the order the resource becomes desired by a higher priority thread and then restores
it in the order of resource deallocation. The sequence of events that happens here is:
start t1: desiredObject1 becomes desired by t1. This associates the current priority
(5) with desiredObject1 and sets the priority to 6.
start t2: desiredObject2 becomes desired by t2. This associates the current priority
(6) with desiredObject2 and sets the priority to 7.
Release desiredObject1: the priority is restored to 5.
Release desiredObject2: the priority is restored to 6.