Win a copy of Murach's Python Programming this week in the Jython/Python forum!
  • Post Reply Bookmark Topic Watch Topic
  • New Topic

Producer/Consumer - how to notify consumer only?  RSS feed

 
Chuck Zheng
Greenhorn
Posts: 5
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Hi

I have seen many examples using wait/notifyAll to sync producer/consumer for a queue. Now my question is when there are many producer and consumer threads blocked on wait-list over the time, how do you wake up consumers only when the queue is not empty (theflip side of the coin is that when the queue is not full, how do you wake up producers only?)

TIA
Chuck
 
Ernest Friedman-Hill
author and iconoclast
Sheriff
Posts: 24215
37
Chrome Eclipse IDE Mac OS X
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
You don't -- not without using multiple locks, anyway, which is generally more trouble than it's worth. That's why virtually every call to wait() should be in a loop. Consumers always say

while (queue.isEmpty()) wait();

and producers always say

while (queue.isFull()) wait();

That way if a Thread wakes up at the "wrong" time, it just goes back to waiting.
[ June 23, 2005: Message edited by: Ernest Friedman-Hill ]
 
Henry Wong
author
Sheriff
Posts: 22832
119
C++ Chrome Eclipse IDE Firefox Browser Java jQuery Linux VI Editor Windows
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
You don't -- not without using multiple locks, anyway, which is generally more trouble than it's worth.


I am not convinced that it is "more trouble than it's worth". I am a big believer that notifications should be specific.

Adding separate locks doesn't remove the need for the while loop, as that is necessary for other reasons, but it removes the need for using the notifyAll() method (allowing you to use the notify() method instead). If you have a large amount of producers and consumers, you will have to wake them all up (with the notifyAll() technique), even if the first thread that wakes up is the one that you want.

Henry
[ June 23, 2005: Message edited by: Henry Wong ]
 
Stan James
(instanceof Sidekick)
Ranch Hand
Posts: 8791
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
I think the Java 5 BlockingQueue solves this. Or maybe it just hides all the nasty bits inside. Take a look at the source & see.
 
Chuck Zheng
Greenhorn
Posts: 5
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Hi Henry,

I agree with you on notification being specific. but up to JDK 1.4.x, I cannot think of a way to achieve this even with multiple locks - the problem with multiple locks is that I have not found a way to release all the locks I've acquired all at once before I release CPU. e.g.

class MTQ {
private Queue q = new Queue();
private Object pubLock = new Object();
private Object subLock = new Object();

public synchronized void enqueue(Object msg) {
while (q.isFull()) {
try { pubLock.wait() } catch (InterruptedException ie) {}
// this wait only release lock on pubLock, not on this MTQ obj
// the result is that nobody can enter this MTQ obj again
}
q.enqueue(msg);
try { subLock.notify() } catch {InterruptedException ie) {}
}

public synchronized Object dequeue() {
// similar approach for dequeue
}
}

Any better ideas?

cheers
chuck
 
Henry Wong
author
Sheriff
Posts: 22832
119
C++ Chrome Eclipse IDE Firefox Browser Java jQuery Linux VI Editor Windows
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
I agree with you on notification being specific. but up to JDK 1.4.x, I cannot think of a way to achieve this even with multiple locks - the problem with multiple locks is that I have not found a way to release all the locks I've acquired all at once before I release CPU. e.g.


You are absolutely right... the issue here is that you need two different condition variables that share the same lock. This was not directly available in Java until 5.0 with the addition of the Lock and Condition class.

Prior to Java 5.0, you'll need to implement your own. It actually isn't hard -- in fact, it is very easy. Go to the O'Reilly website and download the example code for Java Threads. The book is designed for Java 5.0, but still has code that will run for 1.x, in the appendix.

The classes that you are looking for are the Busyflag (the lock) and the CondVar (condition variable). Basically, you create a lock for the container, and then you create two different condition variables that uses the same lock. The code for each class is less than a page long -- but let me know if you have any questions.

Hope this helps,
Henry
 
Henry Wong
author
Sheriff
Posts: 22832
119
C++ Chrome Eclipse IDE Firefox Browser Java jQuery Linux VI Editor Windows
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Originally posted by Stan James:
I think the Java 5 BlockingQueue solves this. Or maybe it just hides all the nasty bits inside. Take a look at the source & see.


This is correct. With the blocking queue, not only will you not need to worry about dealing with notifying the correct thread, you won't even have to deal with synchronization at all. In fact, it is simply a container, used between threads, that happen to wait, in the method calls.

However, I would not recommend looking at the source, if you are a beginner. All the thread code is pretty complex -- everything is written "optimistically" (mainly using the new atomic library). You will need to have a good grasp of thread theory to understand some of the stuff.

Henry
 
Don't get me started about those stupid light bulbs.
  • Post Reply Bookmark Topic Watch Topic
  • New Topic
Boost this thread!