Skip to Main Content

Java Programming

Announcement

For appeals, questions and feedback about Oracle Forums, please email oracle-forums-moderators_us@oracle.com. Technical questions should be asked in the appropriate category. Thank you!

Java threading question

807589Sep 8 2008 — edited Sep 8 2008
Would someone explain why this situation is not working as I expected? I would really like to learn from my mistake but I do not understand why Java is throwing a particular error...

This is a situation where I want to restrict a certain section of a method to one thread at a time. I do not want to make the whole method synchronized (using the synchronized keyword and making it static)

I use one Boolean object as a lock and as a flag to indicate this one section is currently "busy".

One thread grabs a lock, sets it to true, does its work then grabs a lock again, sets it to false and calls notifyAll for anyone else waiting on that lock. But there's some quirky behavior causing it to fail which I don't get yet.

It goes like this:
import java.io.*;
import java.util.*;
import java.text.*;
import java.util.regex.*;
import java.util.zip.*;

public class Test implements Runnable {

	public static void main (String[] args) {
		
		try {
			
			Thread t1 = new Thread(new Test("Thread 1"));
			Thread t2 = new Thread(new Test("Thread 2"));
			t1.start();
			t2.start();
			
		} catch (Exception e) {
			e.printStackTrace();
		}
	}
	
	static String id;
	static Boolean isBusy = Boolean.FALSE;
	
	public Test (String id) {
		this.id = id;
	}

	public void run() {
		try {
			System.out.println(id+" starting");
			
			synchronized (isBusy) {
				if (isBusy.booleanValue()) {
					System.out.println(id+" is waiting");
					isBusy.wait();
					System.out.println(id+" stopped waiting");
				}
				isBusy = Boolean.TRUE;
			}
			
			Thread.sleep(3000);
			
			System.out.println(id+" ending");
			
			synchronized (isBusy) {
				isBusy = Boolean.FALSE;  // LINE 50
				System.out.println(id+" sending notifyAll");
				isBusy.notifyAll(); // LINE 52
			}
		
		} catch (Exception e) {
			System.out.println(id+" error");
			e.printStackTrace();
		}
	}
}
What happens is one thread goes in and correctly grabs the lock and proclaims the section is busy while the other thread correctly waits. But when that thread is done, when I both set the busy flag to false AND call notifyAll I get the "java.lang.IllegalMonitorStateException: current thread not owner" on line 52 (the call to notifyAll).

If I comment out line 50 which unsets the flag, I then don''t have any problems... why is that?

Does line 50 implicitly release the lock? I had no idea that modifying the value of a lock releases it... what would I have to do to make this scenario work correctly?

thanks for you guidance and help!!!
Comments
Locked Post
New comments cannot be posted to this locked post.
Post Details
Locked on Oct 6 2008
Added on Sep 8 2008
4 comments
157 views