Note that there are some explanatory texts on larger screens.

plurals
  1. PO
    primarykey
    data
    text
    <p>For a generic thread safe queue you can use <a href="http://docs.oracle.com/javase/6/docs/api/java/util/concurrent/ConcurrentLinkedQueue.html" rel="nofollow">ConcurrentLinkedQueue</a> or if you want to limit to one object in a queue at a time <a href="http://docs.oracle.com/javase/6/docs/api/java/util/concurrent/SynchronousQueue.html" rel="nofollow">SynchronousQueue</a> finally if one object at a time, but precalculate the next object can be done with <a href="http://docs.oracle.com/javase/1.5.0/docs/api/java/util/concurrent/ArrayBlockingQueue.html" rel="nofollow">ArrayBlockingQueue</a>.</p> <p>The Java memory model allows for effective caching of values, as well as reordering of instructions by a compiler assuming that reordering would not change the results if just one thread were running. As such the producer is not guaranteed to ever view vFlag as true, as it is allowed to use the cached value. Thus the consumer thread sees vflag as true, and the producer sees it as false. Declaring a variable as volatile means that JVM has to look up the value each time, and produces a memory fence between on either side of the access which prevents reordering. For instance</p> <pre><code>public class vFlagClass { public volatile boolean value; } </code></pre> <p>The consumer may continue to access the queue after it sets vFlag true, either the consumer should clear the queue itself, or it needs to wait for a signal from the producer that the queue is cleared. Even assuming value was volatile, it would still be acceptable operation for the program to consume all of the input in the queue after vFlag.value got set true, before activating the producer and clearing the queue.</p> <p>Additionally your queue structure assumes only one thread is writing and one thread is reading, by having the producer clear the queue, the producer is effectively reading from the queue and breaking your invariant.</p> <p>For your error specifically I imagine that what is happening is that the consumer tells the producer to clear the queue when the queue is empty and then tries the queue again, the queue is still empty so it waits. The producer then wakes up, fills the queue, this wakes up the consumer, the producer then clears the queue, the consumer starts going and polls the queue, however the queue is empty. And so NULL is returned. In other words</p> <pre><code>Producer : queue.add(str); // queue size is now 1 Producer : goes to end of loop Consumer : String str = queue.poll(); // queue size is now 0 Consumer : process(str, vFlag); // vFlag.value is set to false Consumer : String str = queue.poll(); // waits at if(queue.size() == 0) { wait(); } Producer : queue.add(str); Producer : notify() // wakes up consumer Producer : queue.clear(); Consumer : String str = queue.poll(); // note queue is empty, so returns NULL </code></pre> <p>In this case you would need to do change PQueue.poll to</p> <pre><code>String str = null; while((str = queue.poll()) == null) wait(); return str; </code></pre> <p>but this is not a good solution as it still has all of the other bugs mentioned earlier. Note: This only allows two threads to read from the queue, it does not protect against multiple threads writing to the queue.</p> <p>Edit: Noticed another race condition, the Producer may put "end" into the queue, the Consumer read and process it, and then the Producer updates exitFlag. Note that changing exitFlag does not fix anything as it has nothing to do with reading stale data. Instead of using an exitFlag, you should have the Consumer also break when it reads "end".</p> <p>See the documentation for more information on <a href="http://docs.oracle.com/javase/tutorial/essential/concurrency/memconsist.html" rel="nofollow">memory consistency in Java</a>.</p>
    singulars
    1. This table or related slice is empty.
    plurals
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. VO
      singulars
      1. This table or related slice is empty.
    2. VO
      singulars
      1. This table or related slice is empty.
    3. VO
      singulars
      1. This table or related slice is empty.
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload