• Post Reply Bookmark Topic Watch Topic
  • New Topic

Thread Madness - please help!  RSS feed

 
Binkie Hayes
Greenhorn
Posts: 20
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Hi everyone!
Would any kind soul out there please be able to help me out with a problem with threading? Am being driven demented!
My code instantiates 3 instances of the same class and increments a shared variable. I want each instance to go to sleep until the variable has reached a certain value through being incremented by other instances of the class. So I thought I could use wait and notifyAll.. here's the code



When I run this code, it throws an IllegalMonitorStateException at the x.notifyAll() line:

Oi 1 Added 1, now x = 1
Whoops id = 1, Illegl java.lang.IllegalMonitorStateException: current thread not
owner
java.lang.IllegalMonitorStateException: current thread not owner
at java.lang.Object.notifyAll(Native Method)
at Oi.run(test.java:29)
at java.lang.Thread.run(Thread.java:534)
Oi 1 WAITING cos x = 1
Oi 2 Added 1, now x = 2
Whoops id = 2, Illegl java.lang.IllegalMonitorStateException: current thread not
owner
java.lang.IllegalMonitorStateException: current thread not owner
at java.lang.Object.notifyAll(Native Method)
at Oi.run(test.java:29)
at java.lang.Thread.run(Thread.java:534)
Oi 2 WAITING cos x = 2
java.lang.IllegalMonitorStateException: current thread not owner
Oi 3 Added 1, now x = 3
Whoops id = 3, Illegl java.lang.IllegalMonitorStateException: current thread not
owner
at java.lang.Object.wait(Native Method)
at java.lang.Object.wait(Object.java:429)
at Oi.run(test.java:40)
at java.lang.Thread.run(Thread.java:534)
java.lang.IllegalMonitorStateException: current thread not owner
at java.lang.Object.notifyAll(Native Method)
at Oi.run(test.java:29)
at java.lang.Thread.run(Thread.java:534)
yay! Oi 3 finished waiting
java.lang.IllegalMonitorStateException: current thread not owner
at java.lang.Object.wait(Native Method)
at java.lang.Object.wait(Object.java:429)
at Oi.run(test.java:40)
at java.lang.Thread.run(Thread.java:534)

I don't understand why the call to notifyAll throws this exception. Its within the synchronized block of code, so surely to enter into this block, the thread MUST get ownership of x's monitor? Or am I barking up the wrong tree completely?
I would be eternally grateful to any of ye gurus out there who can cast some light on this for me - its driving me bonkers
Many thanks!
cheers guys
binkie

[ EJFH: Fixed code tags. Use "[]", not "<>" ].
[ August 04, 2004: Message edited by: Ernest Friedman-Hill ]
 
Ernest Friedman-Hill
author and iconoclast
Sheriff
Posts: 24215
37
Chrome Eclipse IDE Mac OS X
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
After this line

x = x.add(BigInteger.ONE);

"x" refers to a different object. So the object you call notifyAll() on and the one you synchronize on are not the same object; hence, the exception.

You might change everything to synchronize on a special object you create just for this purpose -- i.e.,

private static final Object LOCK = new Object();
 
Binkie Hayes
Greenhorn
Posts: 20
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Ernest you are an absolute star! Thanks a million for that - it made perfect sense when you pointed it out, i just didnt even consider that the object reference was changing
A million thank-yous and good vibes winging their way to you!
eternally grateful,
binkie
 
vikram hegde
Greenhorn
Posts: 18
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Hi All,

Below is the thread program which I'm trying to run and getting "java.lang.IllegalMonitorStateException: current thread not owner"

public class TestThreads {
protected boolean commoditiesReady = false;
public static void main(String[] args) {
TestThreads tt = new TestThreads();
ThreadProducer tP = tt.new ThreadProducer(tt);
ThreadConsumer tC = tt.new ThreadConsumer(tt);
Thread thP = new Thread(tP, "Thread-Producer");
thP.setPriority(Thread.MAX_PRIORITY);
Thread thC = new Thread(tC, "Thread-Consumer");
thC.setPriority(Thread.MAX_PRIORITY);

thC.start();
thP.start();
try {
thC.join();
thP.join();
} catch (InterruptedException e) {
e.printStackTrace();
}
}

class ThreadProducer implements Runnable{
TestThreads tt = null;

ThreadProducer(TestThreads tt){
this.tt = tt;
}

public void run() {
System.out.println(Thread.currentThread().getName()+" - Printing from inside ThreadProducer");
for(int i = 0 ; i< 10; i++)
System.out.println("Producing commodity...");
this.tt.commoditiesReady = true;
notifyAll();
}
}

class ThreadConsumer implements Runnable{
TestThreads tt = null;

ThreadConsumer(TestThreads tt){
this.tt = tt;
}

public void run() {
System.out.println(Thread.currentThread().getName()+" - Printing from inside ThreadConsumer");
if(!this.tt.commoditiesReady){
synchronized(this.tt){
try {
this.tt.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
for(int i = 0 ; i< 10; i++)
System.out.println("Consuming commodity...");
}
}
}

Can any please point out where I'm going wrong and help me in better understaning of the working of threads
 
Steve Luke
Bartender
Posts: 4181
22
IntelliJ IDE Java Python
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
For the future, you should start a new thread when asking a new question. Digging up an old and answered thread will confuse people.

About your problem:

In the ThreadProducer's run method you have:

That notifyAll() is equivalent to this.notifyAll(). As the API for IllegalMonitorException states, the exception you are seeing gets thrown when you use a wait() or notify()/notifyAll() on an object whose lock you don't own. You need to gain the lock for ThreadProducer's 'this' so you can call the notifyAll and inform any threads waiting on the ThreadProducer that it is okay to run. The code may look like this:

That gets rid of the error, but unfortunately won't help synchronize your application. Your ThreadConsumer is waiting on the instance of TestThreads, so when you notifyAll waiters on the ThreadProducer the ThreadConsumer won't see it.

So your task is to modify the code I gave above, which gains the lock on the ThreadProducer and then notifyAll() waiters on the ThreadProducer, into code that will work on the TestThreads instance.
 
vikram hegde
Greenhorn
Posts: 18
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Sorry for Steve for the pickin up the old thread for askin the query. Thanks for making me know my mistake. I will make sure not repeating any time in future.

Also, many many thanks for pointing out that I need to have a lock even while I notify on an Object. Now, I made the changes like

synchronized (this.tt) {
this.tt.notifyAll();
}

in ThreadProducer in the code posted earlier. It started working properly. I had the impression that we need no have a lock while I notify()/notifyAll(). Thanks agian for pointing out this for me.

----New code which works---

public class TestThreads {
protected boolean commoditiesReady = false;
public static void main(String[] args) {
TestThreads tt = new TestThreads();
ThreadProducer tP = tt.new ThreadProducer(tt);
ThreadConsumer tC = tt.new ThreadConsumer(tt);
Thread thP = new Thread(tP, "Thread-Producer");
thP.setPriority(Thread.MAX_PRIORITY);
Thread thC = new Thread(tC, "Thread-Consumer");
thC.setPriority(Thread.MAX_PRIORITY);

thC.start();
thP.start();
try {
thC.join();
thP.join();
} catch (InterruptedException e) {
e.printStackTrace();
}
}

class ThreadProducer implements Runnable{
TestThreads tt = null;

ThreadProducer(TestThreads tt){
this.tt = tt;
}

public void run() {
System.out.println(Thread.currentThread().getName()+" - Printing from inside ThreadProducer");
for(int i = 0 ; i< 10; i++)
System.out.println("Producing commodity...");
this.tt.commoditiesReady = true;
synchronized (this.tt) {
this.tt.notifyAll();
}
}
}

class ThreadConsumer implements Runnable{
TestThreads tt = null;

ThreadConsumer(TestThreads tt){
this.tt = tt;
}

public void run() {
System.out.println(Thread.currentThread().getName()+" - Printing from inside ThreadConsumer");
if(!this.tt.commoditiesReady){
synchronized(this.tt){
try {
this.tt.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
for(int i = 0 ; i< 10; i++)
System.out.println("Consuming commodity...");
}
}
}

Thanks,
Vic
 
It is sorta covered in the JavaRanch Style Guide.
  • Post Reply Bookmark Topic Watch Topic
  • New Topic
Boost this thread!