Working with thread safe collections: ConcurrentStack and ConcurrentQueue

The ConcurrentStack and ConcurrentQueue classes, lock-free and thread-safe implementations of the Stack and Queue classes, build thread safe collections in .Net

ConcurrentStack

ConcurrentStack

Thread safe collections were first introduced in .Net 4 with the introduction of the System.Collections.Concurrent namespace. The collection types in the System.Collections.Concurrent namespace contains a collection of thread safe collection classes.

ConcurrentStack

A stack is a data structure that works on LIFO (last in first out) basis. The ConcurrentStack<T> class is a thread safe counterpart of the generic Stack<T> class. The ConcurrentStack<T> is a thread safe generic collection class that was first introduced as part of .Net Framework 4. Here's the list of the important methods of this class that illustrate the possible operations.

  1. Push(T element) - this method is used to add data of type T.
  2. PushRange - this method can be used to add an array of items of type T.
  3. TryPop(out T) - this method is used to retrieve the first element from the stack. It returns true on success, false otherwise.
  4. TryPeek(out T) - this method is used to retrieve the next element from the stack but it doesn't remove the element from the stack. Note that similar to the TryPop(out T) method, it returns true on success and false otherwise.
  5. TryPopRange - this method is overloaded and works similar to the TryPop but is used for retriving arrays from the stack

Here's how you can create an instance of the ConcurrentStack<T> class and push data to it.

ConcurrentStack<Int32> concurrentStack = new ConcurrentStack<Int32>();

for (Int32 index = 0; index < 10; index++)

{

       concurrentStack.Push(index);

}

To retrieve the elements from out of a concurrent stack, you can leverage the TryPop(out T) method as shown below.

Int32 data;

bool success = concurrentStack.TryPop(out data);

The following code listing illustrates how you can store and retrieve data to and from a concurrent stack.

static void Main(string[] args)

       {

           ConcurrentStack<Int32> concurrentStack = new ConcurrentStack<Int32>();

           for (Int32 index = 0; index < 100; index++)

           {

               concurrentStack.Push(index);

           }

           while (concurrentStack.Count > 0)

           {

               Int32 data;

               bool success = concurrentStack.TryPop(out data);

               if (success)

              {

                   Console.WriteLine(data);

               }

           }

           Console.Read();

       }

When you execute the above code listing, the numbers 0 to 99 will be displayed in the reverse order at the console window.

ConcurrentQueue

A queue is a data structure that works on the basis of FIFO (first in first out). The ConcurrentQueue<T> class in .Net acts as a thread safe FIFO based generic queue.

The following is the list of the important methods in the ConcurrentQueue<T> class.

  1. Enqueue(T element) - this method is used to add an item of type T to the queue
  2. TryPeek(out T) - this method is used to retrieve the next element from the queue but it doesn't remove the element from the queue. This method returns true on success and false when it fails.
  3. TryDequeue(out T) - this method is used to retrieve the first element from the queue. Contrary to the TryPeek(out T) method, it removes the element from the queue. This method returns true on success and false otherwise.

The following code snippet shows how you can create an instance of the ConcurrentQueue class to store integers.

ConcurrentQueue<Int32> concurrentQueue = new ConcurrentQueue<Int32>();

To store elements to the concurrent queue instance you can take advantage of the Enqueue method as shown below.

concurrentQueue.Enqueue(100);

The following code listing illustrates how you can store and retrieve elements to and from a concurrent queue.

ConcurrentQueue<Int32> concurrentQueue = new ConcurrentQueue<Int32>();

for (int index = 0; index < 100; index++)

{

     concurrentQueue.Enqueue(index);

}

Int32 item;

while (concurrentQueue.TryDequeue(out item))

{

     Console.WriteLine(item);

}

When you execute the above code listing, the numbers 0 to 99 will be displayed at the console window.

Note that both ConcurrentStack and ConcurrentQueue classes are thread safe and they can manage locking and synchronization issues internally.

You can also convert the concurrent queue instance to an array by making a call to the ToArray() method. The following code snippet illustrates how this can be achieved.

ConcurrentQueue<Int32> concurrentQueue = new ConcurrentQueue<Int32>();

for (Int32 index = 0; index < 100; index++ )

   concurrentQueue.Enqueue(index);

Int32[] integerArray = concurrentQueue.ToArray();

foreach (int i in integerArray)

{

   Console.WriteLine(i);

}

The IsEmpty property of the ConcurrentQueue class returns true is the collection is empty, false otherwise. The following code snippet shows how you can use this method.

ConcurrentQueue<Int32> concurrentQueue = new ConcurrentQueue<Int32>();

for (Int32 index = 0; index < 100; index++ )

concurrentQueue.Enqueue(index);

while(!concurrentQueue.IsEmpty)

{

     Int32 result;

     concurrentQueue.TryDequeue(out result);

     Console.WriteLine(result);

}

This article is published as part of the IDG Contributor Network. Want to Join?

From CIO: 8 Free Online Courses to Grow Your Tech Skills
Notice to our Readers
We're now using social media to take your comments and feedback. Learn more about this here.