Where do I start with this threading issue?

W

Wes Harrison

I am working on my first multithreaded application and have struck a serious
problem. In the main thread I start 2 new threads, one that creates a large
List (synchronised ArrayList actually) and the other that continually loops
through it printing out any new entries.

The problem is that sometimes (and only sometimes) the thread that prints
out the list entries appears to stall. I have placed print statements
throughout the thread's code and it just seems to stop right between two
print statements. There's nothing else between those two print statements.

So I figure the symptoms must be related to a multithreading issue but I
don't understand the subject well enough to debug it properly. I expect
that I have to synchronize some method or code block but I have no idea
where to start looking.

Do you think this is a thread-related issue? What should I be synchronizing
and where?

Any help greatly appreciated. I can't post the code as my employer won't
allow it.

Wes
 
M

Matt Humphrey

Wes Harrison said:
I am working on my first multithreaded application and have struck a serious
problem. In the main thread I start 2 new threads, one that creates a large
List (synchronised ArrayList actually) and the other that continually loops
through it printing out any new entries.

The problem is that sometimes (and only sometimes) the thread that prints
out the list entries appears to stall. I have placed print statements
throughout the thread's code and it just seems to stop right between two
print statements. There's nothing else between those two print statements.

So I figure the symptoms must be related to a multithreading issue but I
don't understand the subject well enough to debug it properly. I expect
that I have to synchronize some method or code block but I have no idea
where to start looking.

Do you think this is a thread-related issue? What should I be synchronizing
and where?

Any help greatly appreciated. I can't post the code as my employer won't
allow it.

Seemingly random stalling between statements is exactly what bad
synchronization looks like. Although you may think of each thread as
running independently, they are actually being continuously and rapidly run
and suspended by the CPU. The hallmark of a correct multithreaded design is
that you can prove for all cases that the timing of when threads has no
effect on theprogram. I say prove here because you can test and test and
test and test a multithreaded application and always get a correct response
and then run it on a different machine (or with a different load or
different data or anything) and get the synchronization error right away.

So for your case all we know about is that one thread puts things into the
list and the other reads the list. Although the list is synchronized, that
simply means that only one thread can be executing any of the synchronized
methods at any time. However, that only applies to one method at a time.
Between any two method calls the list may be changed. For example:

for (int i = 0; i < list.size (); ++i) {
print (list.get (i));
}

Between the initial list size request and the retrieval of each element the
list may be changing, even though both the size () call and the get () call
are synchronized. Removing items from the list will make this fail.

There are several things I recommend. First, check to make sure that any
exceptions generated by the threads are printed out so that you'll know
whether the problem is deadlock or bad synchronization causing an exception.
Next, get a good book on threading (if you havn't already) such as Paul
Hyde's "Java Thread Programming" . Build a small, separate prototype of a
program that creates a list and has one thread adding and another thread
printing so that you can understand the issues without the complexity of the
real application and so that if you run into trouble you can post the code.
As you do this, keep in mind that the two threads may stop and restart not
just at any time, but at the worst possible times and ensure that the data
is safe at those times.

Finally, as you head back to your real application, don't forget that
although the list is synchronized, the individual data items are not. Is it
possible the list is changing one while the other is trying to print it out?
(E.g. is the item created and fields assigned and then added to the list, or
is it created and added to the list and then has its fields assigned. In
the latter case the reading thread may encounter the item before you've
really finished creating it.)

Good luck,
Matt Humphrey (e-mail address removed) http://www.iviz.com/
 
W

Wes Harrison

Matt Humphrey said:
Seemingly random stalling between statements is exactly what bad
synchronization looks like. Although you may think of each thread as
running independently, they are actually being continuously and rapidly run
and suspended by the CPU. The hallmark of a correct multithreaded design is
that you can prove for all cases that the timing of when threads has no
effect on theprogram. I say prove here because you can test and test and
test and test a multithreaded application and always get a correct response
and then run it on a different machine (or with a different load or
different data or anything) and get the synchronization error right away.

So for your case all we know about is that one thread puts things into the
list and the other reads the list. Although the list is synchronized, that
simply means that only one thread can be executing any of the synchronized
methods at any time. However, that only applies to one method at a time.
Between any two method calls the list may be changed. For example:

for (int i = 0; i < list.size (); ++i) {
print (list.get (i));
}

Between the initial list size request and the retrieval of each element the
list may be changing, even though both the size () call and the get () call
are synchronized. Removing items from the list will make this fail.

There are several things I recommend. First, check to make sure that any
exceptions generated by the threads are printed out so that you'll know
whether the problem is deadlock or bad synchronization causing an exception.
Next, get a good book on threading (if you havn't already) such as Paul
Hyde's "Java Thread Programming" . Build a small, separate prototype of a
program that creates a list and has one thread adding and another thread
printing so that you can understand the issues without the complexity of the
real application and so that if you run into trouble you can post the code.
As you do this, keep in mind that the two threads may stop and restart not
just at any time, but at the worst possible times and ensure that the data
is safe at those times.

Finally, as you head back to your real application, don't forget that
although the list is synchronized, the individual data items are not. Is it
possible the list is changing one while the other is trying to print it out?
(E.g. is the item created and fields assigned and then added to the list, or
is it created and added to the list and then has its fields assigned. In
the latter case the reading thread may encounter the item before you've
really finished creating it.)

Good luck,
Matt Humphrey (e-mail address removed) http://www.iviz.com/

Thank you very much for this Matt. I have tried to add synchronized methods
and sections into the code but it has only made things worse. Now, nothing
is outputted at all. The printing thread stalls almost immediately. Also,
there are no exceptions occurring.

How do I determine if this is a deadlock issue or some other kind of
synchronisation issue? Why would synchronizing code make matters worse? I
feel a bit lost with this whole thing...

Wes
 
J

John C. Bollinger

Wes said:
Thank you very much for this Matt. I have tried to add synchronized methods
and sections into the code but it has only made things worse. Now, nothing
is outputted at all. The printing thread stalls almost immediately. Also,
there are no exceptions occurring.

First, I recommend that instead of a Vector or another synchronized
List, you use a plain ArrayList or LinkedList and perform all
synchronization explicitly in your own code. As Matt pointed out,
synchronized lists of the kind available directly from the platform API
are generally not sufficient to ensure thread safety, so they don't
offer much advantage in most situations. They do, however, make it a
bit less obvious where synchronization occurs.
How do I determine if this is a deadlock issue or some other kind of
synchronisation issue? Why would synchronizing code make matters worse? I
feel a bit lost with this whole thing...

There are only two main kinds of synchronization issues: deadlock and
data corruption. The first happens when two or more threads prevent
each other from proceeding, and the second occurs only if two or more
threads don't take sufficient care to avoid reading / manipulating the
same data at the same time. If your application stalls then you have a
deadlock, although there might be other problems as well that lead up to it.

Synchronization in the wrong place, at the wrong time, or in the wrong
way is what _causes_ deadlock. Adding additional synchronization to an
application that has a deadlock problem already can therefore easily
accentuate the problem. Depending on the details, however, it can also
suppress the problem.

For a model app as simple as you describe, you should observe the
following principles: threads should hold an object's monitor (lock) for
exactly as long as they need to do and exactly when they need to do. No
more, no less. If possible, threads should not run at all unless they
have work to do. Your continuously looping thread sounds like it
violates that principle. Look into Object.wait() and Object.notify() /
Object.notifyAll() for ways to control when threads can run.

Overall, do perform all the synchronization in your own code, and
understand at every synchronization point exactly why you are
synchronizing there. Understand at every unsynchronized access to a
shared object exactly why you are _not_ synchronizing _there_. Don't
ever perform an action in a synchronized section of code that requires
an indeterminate time to complete.

I doubt whether you'll get much better from us if you can't give us any
code (even model code) to comment on. You may, however, find the Java
Tutorial's section on multithreading to be of use to you -- look for it
on java.sun.com.


John Bollinger
(e-mail address removed)
 
W

Wes Harrison

John C. Bollinger said:
First, I recommend that instead of a Vector or another synchronized
List, you use a plain ArrayList or LinkedList and perform all
synchronization explicitly in your own code. As Matt pointed out,
synchronized lists of the kind available directly from the platform API
are generally not sufficient to ensure thread safety, so they don't
offer much advantage in most situations. They do, however, make it a
bit less obvious where synchronization occurs.


There are only two main kinds of synchronization issues: deadlock and
data corruption. The first happens when two or more threads prevent
each other from proceeding, and the second occurs only if two or more
threads don't take sufficient care to avoid reading / manipulating the
same data at the same time. If your application stalls then you have a
deadlock, although there might be other problems as well that lead up to it.

Synchronization in the wrong place, at the wrong time, or in the wrong
way is what _causes_ deadlock. Adding additional synchronization to an
application that has a deadlock problem already can therefore easily
accentuate the problem. Depending on the details, however, it can also
suppress the problem.

For a model app as simple as you describe, you should observe the
following principles: threads should hold an object's monitor (lock) for
exactly as long as they need to do and exactly when they need to do. No
more, no less. If possible, threads should not run at all unless they
have work to do. Your continuously looping thread sounds like it
violates that principle. Look into Object.wait() and Object.notify() /
Object.notifyAll() for ways to control when threads can run.

Thanks for the help. I have rewritten the code to use wait() and
notify()(as I have come to understand them) and now have the continuously
looping thread only run when it has something to output. However, I
obviously don't understand wait() and notify() properly as I get the
following exception:

java.lang.IllegalMonitorStateException: current thread not owner
at java.lang.Object.wait(Native Method)
at java.lang.Object.wait(Object.java:429)

when I do this:

try
{
this.wait();
}
catch (InterruptedException ex)
{
System.out.println("InterruptedException: " + ex);
}

inside the outputting thread. What does this mean? Are these methods
supposed to be called from the thread that spawns the sub-thread? I thought
I could call wait() on myself and wait until I am notified by another thread
after which I would pick up after the wait() line. Is this not correct? I
am quite confused now!

I am sure that wait() and notify() are the way to solving my problems so
your further assistance would be much appreciated.

Wes
 
J

John C. Bollinger

Wes said:
Thanks for the help. I have rewritten the code to use wait() and
notify()(as I have come to understand them) and now have the continuously
looping thread only run when it has something to output. However, I
obviously don't understand wait() and notify() properly as I get the
following exception:

java.lang.IllegalMonitorStateException: current thread not owner
at java.lang.Object.wait(Native Method)
at java.lang.Object.wait(Object.java:429)

when I do this:

try
{
this.wait();
}
catch (InterruptedException ex)
{
System.out.println("InterruptedException: " + ex);
}

inside the outputting thread. What does this mean? Are these methods
supposed to be called from the thread that spawns the sub-thread? I thought
I could call wait() on myself and wait until I am notified by another thread
after which I would pick up after the wait() line. Is this not correct? I
am quite confused now!

I am sure that wait() and notify() are the way to solving my problems so
your further assistance would be much appreciated.

An object's wait() and notify() methods may only be invoked by a thread
that holds the object's "monitor" (i.e. its lock). Put the wait()
invocation inside a synchronized block to achieve that.

Also, from your code snippet I am suspicious that you are making a
mistake fairly common to those new to wait / notify: for two or more
threads to use wait() and notify() to synchronize their actions, they
must wait() and notify() on the _same_object_. Waiting on "this" is a
red flag here -- it could be made to work that way, but more likely it
is an error. Your List seems to be a natural choice for the
synchronization object, however.


John Bollinger
(e-mail address removed)
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,744
Messages
2,569,483
Members
44,901
Latest member
Noble71S45

Latest Threads

Top