Win a copy of Re-engineering Legacy Software this week in the Refactoring forum
or Docker in Action in the Cloud/Virtualization forum!
  • Post Reply
  • Bookmark Topic Watch Topic
  • New Topic

ArrayBlockingQueue's poll method creates selfish thread

 
Derik Davenport
Ranch Hand
Posts: 90
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
I have a serial I/O monitor thread. that parses data form a serial port. This (low level) thread works by calling Thread.sleep(10) then waking up to check for the existence of data. If it finds none, it immediately sleeps again. When data arrives, it is parsed in that thread. If it is found to be complete and proper it is published by dropping a copy of the data into an ArrayBlockingQueue object.

I have a second, (high level) thread monitoring that same ArrayBlockingQueue for completed messages.

If my high level thread calls , then I get one of 2 behaviors (Windows XP Java 6u34)

1. If a completed message is already waiting on the queue, then the poll method returns immediately. No problem.
2. If no message is on the queue, the call to poll will wait the full 500ms and then return null. Nearly instantaneously thereafter, the (low level) serial monitor thread will get a time slice from the JVM, discover a completed message, and place it on the queue.

Now I know for a fact that if the remote device on the serial port responds at all it is guaranteed to happen within 200ms and usually within 20ms. So this means that for 300+ms, there was data waiting, but the serial monitor thread was not acting on this data. This seems to be because the call to poll is a selfish thread which prevents other thread from running. To test that theory I replaced the call above with the following loop.



This seems to completely fix my problem. Typically within a few tens of milliseconds, the low level serial monitor thread will receive data; and the high level thread monitoring the ArrayBlockingQueue will see the data almost immediately thereafter. But I have nagging doubts about this solution because of some unanswered questions.

Shouldn't the Windows XP version of the JVM use time slicing to ensure that the poll statement is not selfish?
Is using the poll function in a non-selfish loop like the one above the only way to safely use the poll method? If so, why would carefully crafted concurrent package create a blocking function that is potentially a selfish thread?



Just for your reference, If you look that source code for the method in java.util.concurrent.ArrayBlockingQueue, you will find the following code.



The call to notEmpty.awaitNanos relies on code found in a method of the same name of a ConditionObject object. In turn, ConditionObject is a public inner class of java.util.concurrent.locks.AbstractQueuedSynchronizer.


 
Henry Wong
author
Marshal
Pie
Posts: 20894
76
C++ Chrome Eclipse IDE Firefox Browser Java jQuery Linux VI Editor Windows
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Derik Davenport wrote:
Shouldn't the Windows XP version of the JVM use time slicing to ensure that the poll statement is not selfish?
Is using the poll function in a non-selfish loop like the one above the only way to safely use the poll method? If so, why would carefully crafted concurrent package create a blocking function that is potentially a selfish thread?



Windows XP supports preemptive timeslicing. Furthermore, there is even logic to prevent thread starvation that bumps the effective priority of lesser ran threads .... so what you are describing should never happen !!


*AND* also...

Derik Davenport wrote:
Just for your reference, If you look that source code for the method in java.util.concurrent.ArrayBlockingQueue, you will find the following code.



The call to notEmpty.awaitNanos relies on code found in a method of the same name of a ConditionObject object. In turn, ConditionObject is a public inner class of java.util.concurrent.locks.AbstractQueuedSynchronizer.


As you pointed out, threads waiting for data uses condition variables -- the concurrent library replacement for the wait/notify mechanism -- which means that the thread is not in a runnable state when it is waiting. Only runnable threads can run, so the thread could not be scheduled at all.


Don't know what the issue is ... but there is definitely something else going on here.

Henry
 
Tony Docherty
Bartender
Posts: 2942
59
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Rather than the high level thread being selfish it is more likely that the low level thread is being blocked from running in some way. Can you show the code for your low level thread. Are you using synchronized blocks anywhere or any other forms of locks?
 
  • Post Reply
  • Bookmark Topic Watch Topic
  • New Topic