English 中文(简体)
Java threading problem
原标题:

I m using multiple threads in my application. Basically I have a combo box and upon selecting Inbox, p1 resumes and p2 is suspended and upon selecting Send, p2 starts and p1 stops. Below is the code (I m sure it s not perfect)

public void modifyText(ModifyEvent e) {
                if (combo.getText().equals("Inbox"))
                {
                    synchronized(p2) 
                    {
                        p2.cont = false;
                    }
                    table.removeAll();
                    synchronized(p1)
                    {
                        p1.cont = true;
                        p1.notify();
                    }
                }


                else if (combo.getText().equals("Sent"))
                {
                    synchronized(p2) 
                    {
                        p1.cont = false;
                    }
                    table.removeAll();
                    synchronized(p1)
                    {
                        p2.cont = true;
                        p2.notify();
                    }
                }
            }
        });

and for P1 and P2 I have this inside their while loops:

synchronized (this) {
            while (cont == false)
                try {
                    wait();
                } catch (Exception e) {
                }
        } 

... As it is it s now working (I m a beginner to threads). On pressing Sent in the combo box, I get an IllegalStateMonitorException. Could anyone help me solve the problem plz?

Thanks and regards, Krt_Malta

最佳回答

the problem is here:

synchronized(p1)
{
    p2.cont = true;
    p2.notify();
}

You are doing p2.notify() when you haven t got a lock on p2 (you must hold the monitor to call notify on it). Change synchronized(p1) to synchronized(p2). Additionally, you need to reverse the other synchronized clause as well which is also faulty. So, as an example:

synchronized(p1) 
{
    p1.cont = false;
    // p1.notify(); <- do you need this here?
}
table.removeAll();
synchronized(p2)
{
    p2.cont = true;
    p2.notify();
}

Additionally, your other code is a bit wrong too, it s very bad practice to lock inside an entire loop, make it a bit more atomic.

while (!cont) {
    synchronized (this) {
       try {
           wait();
       } catch (Exception e) {
       }
    }
}

Additional optimisation, avoid synchronised if possible:

if (p1.cont) {
   synchronized(p1) 
   {
       p1.cont = false;
       // p1.notify(); <- do you need this here?
   }
}
table.removeAll();

if (!p2.cont) {
   synchronized(p2)
   {
       p2.cont = true;
       p2.notify();
   }
}

Make the cont field volatile here, and mirror for the other part of the if statement as appropriate.

Edit: looking back on this and battling with a concurrency bug I was recently facing, anyone implementing this pattern might face a problem with an infinite wait, if an object being locked & half-locked on is being looked at by the conditional of the while loop (this is because there is a gap where the state can change between evaluating the conditional and the imposition of the wait statement). In this case, place the synchronized block on the outside of the loop.

问题回答

In this code

                synchronized(p1)
                {
                    p2.cont = true;
                    p2.notify();
                }

You re synchronizing on p1 but calling notify() on p2, which leads to the exception.

You can t wait in awt event dispatch thread or else that will hold up your entire app. Read about http://en.wikipedia.org/wiki/Event_dispatching_thread

Also you shouldn t use raw threads unless you really know what you are doing. Check out http://java.sun.com/javase/6/docs/api/java/util/concurrent/package-summary.html and read up on Executors





相关问题
Spring Properties File

Hi have this j2ee web application developed using spring framework. I have a problem with rendering mnessages in nihongo characters from the properties file. I tried converting the file to ascii using ...

Logging a global ID in multiple components

I have a system which contains multiple applications connected together using JMS and Spring Integration. Messages get sent along a chain of applications. [App A] -> [App B] -> [App C] We set a ...

Java Library Size

If I m given two Java Libraries in Jar format, 1 having no bells and whistles, and the other having lots of them that will mostly go unused.... my question is: How will the larger, mostly unused ...

How to get the Array Class for a given Class in Java?

I have a Class variable that holds a certain type and I need to get a variable that holds the corresponding array class. The best I could come up with is this: Class arrayOfFooClass = java.lang....

SQLite , Derby vs file system

I m working on a Java desktop application that reads and writes from/to different files. I think a better solution would be to replace the file system by a SQLite database. How hard is it to migrate ...

热门标签