views:

151

answers:

4

Hi,

I have to design multithreaded module for a problem. And problem is, I have queue, there is a one thread which is putting messages in the message queue, and there are two thread say A and B, thread A process the even message (0,2,4..) and thread B processes the odd message(1,3,5..). I came up with two solution, first one is using two events(say X and Y) event X is for thread A and Y is for thread B. I check if the message is at even position, I set the event X for thread A, and Y for thread B otherwise. And the second solution is by having two seperate quest for each thread. A thread will put even position messages to queue of thread A and odd messages to the queue of thread B, with this solution thread A and B can work asynchronously. Am i right, or is there any other elegant solution?

Thanks.

+6  A: 

Using only one queue and synchronizing A and B in order to ensure a proper fetching sequence is a complete nonsense.

Just use two queues, one for A and one for B, and ensure that they are filled correctly (which seems an easier and cleanier problem by far, even from a design PoV.

akappa
-1 What if the OP later decides to use 4 worker threads? 16 threads? You have obviously never heard of thread pools and worker queues.
Emile Cormier
Assuming that the requirement is the strict processing of messages by strict threads, then separate queues is appropriate.
Will
@Will: Hmm, good point. I'll prompt the OP to clarify this matter. I wish I could undo my -1.
Emile Cormier
@Will: A strict message/thread requirement seems a bit contrived. It would be easy to make it so that worker threads can query the even/odd-ness of the message they're processing. I stand by my -1. :P
Emile Cormier
@Emile, seeing as the OP explicitly described this this two-queue design as being applicable, I'd say that akappa's advice was sound.
Will
@Will: I concede your point. I'll +1 one of akappa's other answers for balance.
Emile Cormier
@Emile: I've extensively used thread pools, master/workers and a bunch of patterns for handling concurrence. My advice follows from the requirement outlined by the OP, not by sheer ignorance. That requirement may sounds strange (in fact it SOUNDS strange), probably that requirement can be relaxed by a better design, but while that requirement sticks, separate queues are the most natural way to do the job.
akappa
@akappa: Gotcha. I was too quick to criticize. I'm sorry. :-( It's just that the "complete nonsense" part of your answer sounded rather harsh (especially since it would not be nonsense to use a single queue when implementing the thread pool pattern).
Emile Cormier
@Emile It's a complete nonsense to use only one queue AND to syncronize the threads in order to ensure the correct fetch sequence (A gets 1, 3, 5, 7, ...; B gets 2, 4, 6,... etc); of course the ThreadPool pattern is the best thing to use, if applicable, because it decouples logic from threads communications. ;)
akappa
IMHO, thread pools are good, when messages to be processed without any restriction( unike i have). In this case thread can simply fetch the message from the queue and process it without any synchronization. Flexibility here is you can have more threads. But my requirement is very strict. So I think, seperate queue will work much better.
Reader
@Emile: Sorry for my harshness, it wasn't intended :)
akappa
A: 

Elegant solution:

  • Maintain a single lock for the queue
  • Use three semaphores (one for each thread)
    • WriteThreadSem
    • OddReadSem
    • EvenReadSem

Have the write thread obtain the queue lock, write the entry, release the lock... Meanwhile the even and odd threads acquire their respective semaphores. Once it is done writing the writing thread wakens the thread via its respective semaphore that is next to read. The waking thread acquires the queue lock and reads its data.. Releases the lock, wakes the write thread semaphore.. The write thread determines if it needs to write or what the next read thread needs to be wakened...

Done.

Harley Green
Elegant? This is a mess!
akappa
Best you can do with a multi-threaded solution... You already posted the option for using multiple queues...
Harley Green
This is probably a good solution if you have the constraint to use only a single queue, but I found that constraint "strange" (and probably, in a context with such exotic constraint, you can't afford the luxury to use four locks). So I can't see the point of such perversion ;)
akappa
A: 

Or you could easily write a thread-safe single queue model using basic mutexes.

http://www.justsoftwaresolutions.co.uk/threading/implementing-a-thread-safe-queue-using-condition-variables.html

Xorlev
A: 

What you're describing is very similar to a thread pool or work queue. In your case, you only have two worker threads in the pool. I believe the Intel Thread Building Blocks library supports thread pools.

Assuming that there is no requirement that even/odd messages be strictly processed by their respective threads, you can use a single thread-safe producer/consumer queue, and make your two consumer threads dequeue messages in a first-come/first-serve basis. No need to restrict odd messages to thread A, and even messages to thread B. The first-come/first-serve solution is more readily scalable if you later decide to increase the number of worker threads (for example 4 threads to be run on a quad core).

Emile Cormier