views:

310

answers:

3

I have two threads that want to synchonize on the same object. Thead A needs to be able to interrupt Thread B if a certain condition has been fullfilled. Here is some pseudo-code of what the two threads do/should do.

A:

public void run()
{
    while(true)
    {
        //Do stuff
        synchronized(shared)
        {
            //Do more stuff
            if(condition)
            {
                B.interrupt();
            }
        }
    }
}

B:

public void run()
{
    while(true)
    {
        try
        {
            //Do stuff
            synchronized(shared)
            {
            //Do more stuff
            }
        }
        catch(InterruptedException e)
        {
            continue;
        }
    }
}

Here's the situation I can't resolve. Thread A grabs the shared resource and does some stuff. Meanwhile, Thread B reaches the synchronized block, and awaits for A to release its shared resource. Thread A, while doing stuff, realized that Thread B should not have the shared resource, and tries to interrupt Thread B. But Thread B has already surpassed the points where an InteruptedException could be thrown.

My question is, is there any way to interrupt a thread while it is waiting to be synchronized on something?

+3  A: 

For this kind of thing, you should use the classes in java.util.concurrent.locks - they have far more capabilities, including interruptable locks.

Edit: If you cannot use those classes, then look at jkff's answer - your requirements can be met with the wait()/notify() mechnism, but it's easy to introduce subtle bugs.

Michael Borgwardt
I was afraid that that might be the solution: I'm working with a subset of Java, which doesn't have those classes by default. Are they pure Java (in which case I could include them anyway), or do they require native libraries (a no-go)?
Eric
It's pure Java, introduced in Java 1.5
Valentin Rocher
@Eric, what subset? Is it j2me?
finnw
@Valentin: I wouldn't be 100% certain about that. It might be true for the locks, but the java.util.concurrent.atomic classes definitely use native stuff (though they're specified in a way that they can be implemented less efficiently in pure Java, the JDK source code uses native calls).
Michael Borgwardt
@finnw: No. I'm using LeJOS NXJ, a Java language for the Lego Mindstorms NXT Microcontroller.
Eric
if it's of any help, here is a backport of java.util.concurrent for JVM without it : http://backport-jsr166.sourceforge.net/index.php (I don't know however if it will work with yours)
Valentin Rocher
A: 

Indeed you should use the locks or implement your stuff with the Object.wait(), Object.notify() and Object.notifyAll() methods (locks are actually implemented with them). Do not forget to handle the so-called 'spurious wakeups' (wait() may return even if noone called notify() or notifyAll(), so it should always be called in a loop that checks that the condition you're waiting for is satisfied).

jkff
A: 

No, but ReentrantLock.lockInterruptibly() behaves similarly to the primitive monitorenter instruction and can be interrupted.

finnw