As the title suggests, this is a Producer/Consumer implementation using Semaphores.
There are no deadlocking issues, but it seems whenever the Consumer looks to remove the next item in the queue, it is always the tail.
Pseudo-code:
class Consumer {
while (!q.isEmpty() || !dataRead())
{
empty.acquire();
mutex.acquire();
queue.remove();
mutex.release();
full.release();
}
synchronized (caller)
{
caller.dataWritten = true;
caller.notify();
}
}
class Producer {
for (int i=0; i < 100; i++)
{
full.acquire();
mutex.acquire();
queue.add(i);
mutex.release();
empty.release();
}
...also notify Consumer that we're done...
}
class MainThread {
...
new Thread(new Producer(args)).start();
new Thread(new Consumer(args)).start();
synchronized (this) {
while (!dataWritten())
wait();
...
}
The output looks something like this:
- Item 0 produced...value 0.
- Item 1 produced...value 1.
- Item 0 consumed...value 1.
- Item 1 consumed...value 1.
Obviously, as I'm removing the head, I am expecting removal to be in the same order (FIFO).
I am using a ConcurrentLinkedQueue implementation, but have tried many other implementations like LinkedList, BlockingQueue implementations, etc.
Also, I have attempted to synchronize on the queue object and make the variable volatile as well in ditch efforts, but it did not make a difference.
I am thinking it has to do with a stale reference to the queue, but have run out of ideas to try.
EDIT: What is wrong with the output is that when Item 0 was consumed, it should have consumed value 0, not 1, because that was what was produced for Item 0.
I can't seem to reproduce using minimal code.
It seems if the data comes from an Iterator that takes a small amount of time to read information, the output is off (like in my example), but if I just shove some constant values in, the output is correct. Since there is only 1 Producer, why should this make a difference?