views:

1548

answers:

6

Should FIFO queue be synchronized if there is only one reader and one writer?

+2  A: 

Yes, if the reader and writer interact with the FIFO queue from different threads.

ng
A: 

Depending on implementation, but most likely. You don't want reader to read partially written data.

Domchi
A: 

Yes, unless its documentation explicitly says otherwise.

(It is possible to implement a specialized FIFO that doesn't need synchronization if there is only one reader and one writer thread, e.g. on Windows using InterlockedXXX functions.)

oefe
A: 

I don't see your point, why that should be done if they access different memory, one in the beginning and another int the end?

Arthur
What if there is only one item in the queue? I.e. the beginning and the end are the same? (Or worse - the reader attempts to access when the writer is halfway through the insertion process). In other words, yes in this scenario it should be thread-safe.
Andrew Rollings
If there is only one item, then reader will point to it, writer points to the next position.If there is no items, reader == writer, reader returns null. only when writer completes and moves to the next position, reader will be able to read.I don't see the need for synchronization :(
Arthur
Andreas Huber
Without using synchronization primitives, you *might* get the first correct but you have no way of getting the second.
Andreas Huber
@Andreas Huber: What about the current case with FIFO queue? I don't see where two threads may work with invalid state.
Arthur
Suppose the values written and read are doubles, and suppose the writer had the chance to write just the first 32 bits of the result (assuming its a 32bit processor) and at that point of time its time is up (threads switched).Even a simple assignment operation may be interleaved.
tafa
I agree, what about a more specific case, where the object in the stack is 32bit such as void*?
Arthur
In that case I don't see any problem if the processor is at least 32bit.
tafa
@Arthur: As I said, corruption is probably not a problem if you are careful, but without employing any synchronization primitives there's no way to get around the visibility problems. For an example, see http://stackoverflow.com/questions/434890/is-a-string-property-itself-threadsafe#435045
Andreas Huber
+3  A: 

What do you mean by "synchronized"? If your reader & writer are in separate threads, you want the FIFO to handle the concurrency "correctly", including such details as:

  • proper use of FIFO API should never cause data structures to be corrupted
  • proper use of FIFO API should not cause deadlock (although there should be a mechanism for a reader to wait until there is something to read)
  • the objects read from the FIFO should be the same objects, in the same order, written to the FIFO (there shouldn't be missing objects or rearranged order)
  • there should be a bounded time (one would hope!) between when the writer puts something into the FIFO, and when it is available to the reader.

In the Java world there's a good book on this, Java Concurrency In Practice. There are multiple ways to implement a FIFO that handles concurrency correctly. The simplest implementations are blocking, more complex ones use non-blocking algorithms based on compare-and-swap instructions found on most processors these days.

Jason S
+1  A: 

Try this code for concurrent fifo usage:

public class MyObjectQueue {

private static final ReentrantReadWriteLock lock = new ReentrantReadWriteLock();

private static final ReadLock readLock;

private static final WriteLock writeLock;

private static final LinkedList<MyObject> objects;

static {
 readLock = lock.readLock();
 writeLock = lock.writeLock();
 objects = new LinkedList<MyObject>();
}

public static boolean put(MyObject p) {
 writeLock.lock();
 try {
  objects.push(p);   
  return objects.contains(p);
 } finally {
  writeLock.unlock();
 }
}

public static boolean remove(MyObject p) {
 writeLock.lock();
 try {
  return objects.remove(p);   
 } finally {
  writeLock.unlock();
 }
}

public static boolean contains(MyObject p) {
 readLock.lock();
 try {
  return objects.contains(p);   
 } finally {
  readLock.unlock();
 }
} 

public MyObject get() {
 MyObject o = null;
 writeLock.lock();
 try {
  o = objects.getLast();
 } catch (NoSuchElementException nse) {
  //list is empty
 } finally {
  writeLock.unlock();
 }
 return o;
}

}

Mondain