Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is copying of entire Queue<T> with operator "=" thread safe (C#)

I have generic Queue<T> (System.Collections.Generic) which is accessed for writing from one thread. And it must be accessed from another thread for reading.

I don't want to do any process synchronization (which includes using ConcurrentQueue<T>) for performance reasons. So I came up with idea to copy the entire queue to another queue object of same type in the reading thread. Subsequent operations in the reading thread will be done on the copy. Copying will be done with simple operator =.

Here is some pseudo-code:

//Creating main queue
Queue<MyType> queue1 = new Queue<MyType>();

Writing thread:

//Perform writing in the main queue
queue1.Enqueue(object);
...
queue1.Dequeue();

Reading thread:

//Copy main queue 
Queue<MyType> queue2 = queue1;
//perform all operations in reading thread on queue2

So is such solution thread safe?

UPD: Thank you very much, I wasn't aware that this is merely copying of the link. So Is there a way to copy entire object by value in thread-safe manner?

like image 378
Ivan Smirnov Avatar asked Feb 13 '12 17:02

Ivan Smirnov


1 Answers

Queue<T> is a reference type. So assigning queue1 to queue2 does only copy the reference, not the queue itself.

The assignment itself is atomic and thus thread-safe. Accessing queue1 in one thread, and queue2 in another is no safer that accessing queue1 from both of them. i.e. it is unsafe.

I believe ConcurrentQueue<T> uses "lockless" programming techniques (Interlocked.Exchange and friends) and is pretty fast. You should benchmark it first, before excluding it as a solution.

Copying a Queue<T> will certainly be slower than just using ConcurrentQueue<T>.


On my 2.6GHz system ConcurrentQueue<object> manages 15 million enqueue/dequeue pairs per second compared to 40 million with with Queue<object>. So Queue<object> is about three times as fast.

200 CPU cycles for an enqueue/dequeue pair is pretty cheap. If that is the bottleneck, try using more granular items in the queue.

like image 142
CodesInChaos Avatar answered Sep 24 '22 00:09

CodesInChaos