data shared between threads and synchronized on different objects
I have a thread (the essential piece of its code can be found here:
http://pastebin.com/KM8Yiqgs) which sends some objects ("tasks") over
the network (in method tryToSendTask). Another thread submits objects
to be sent by means of the first thread's method submit - namely, the
"task" is put into queue.
The sending thread "goes to sleep" when the queue is empty but is
woken up if someone calls its submit method. The problem is that we
need to flush the stream before letting the thread sleep. It might be
a little time-consuming operation, so I do it outside synchronized
section (lines 25-31). The problem is that meanwhile someone can add a
new task to the queue. Moreover, before going definitely to sleep
(line 35), I check some flags which can tell me that someone wants my
thread to finish (goOn=false means finishing no matter what,
waitableClosing=true means that we should finish the thread after
sending out the last task from the queue, i.e. only if the queue is
My biggest concern is to avoid the following scenario:
- due to discovering that the queue (line 19) is empty the output
stream is flushed
- during flush some objects are added to the queue and flag
waitableClosing is set to false
- let's assume that there is no line 29 in my code
- due to waitableClosing=true the thread ends (goOn=false is set in
- as a result, last task objects are never sent
This scenario is something I didn't think about on the beggining, so
after some debugging I decided to add line 29 :) But now I'm afraid of
the weird synchronization thing. Let's assume that the flags goOn and
waitableClosing are synchronized on the this reference, but the task
queue has its own synchronization. Is it possible that my thread will
see the old (not refreshed) state of the queue (i.e. empty) but the
new value of the flag responsible for ending the thread? Which would
mean that the bug is still present in my code...
A possible remedy involves adding the synchronized attribute to the
entire submit method, but using a synchronized collection then seems
to be an overkill. On the other hand, we have to add a synchronized
section around line 24 where we read the state of the queue...
....don't we? Maybe we don't. Determining the queue is empty costs us
flushing the stream, but then the state of the queue will be checked
again in line 34 (inside the synchronized section).
What do you think?
Re: data shared between threads and synchronized on different objects
On 8/2/2011 8:06 AM, Marcin Rodzik wrote:
> - due to discovering that the queue (line 19) is empty the output
> stream is flushed
> - during flush some objects are added to the queue and flag
I didn't look at your code, but this shouldn't be a problem. What kind
of queue are you using? You should be using something like BlockingQueue.
1. Poll the queue, send if not empty; repeat until empty.
2. If empty, flush
3. After flushing, block on the queue. When new items are added, you'll
wake up. You'll also wake up right away if some item was added to the
queue in the meantime.
That's it. Once you have a correctly synchronized queue, all the
worries go away. If you can't use BlockingQueue for some reason, then
you should code an object that works like it yourself. It shouldn't be
|All times are GMT. The time now is 12:41 PM.|
Powered by vBulletin®. Copyright ©2000 - 2014, vBulletin Solutions, Inc.
SEO by vBSEO ©2010, Crawlability, Inc.