Home > Net >  C# WPF, Multi-Threads for Queue
C# WPF, Multi-Threads for Queue

Time:04-28

Thread1 does Enqueue() Thread2, 3 does Dequeue()

Thread 2, 3 has same mutex, when i used different mutex, sometime dequeue works twice.

  1. When i use same mutex in Thread 1,2,3 it works fine. What is difference between using same mutex in Thread 1,2,3 and thread1_mutex for Thread1, thread2_mutex for Thread 2,3?

  2. How to prevent dequeue (Thread 2 and 3) working twice for same value? if dequeue works twice for same value, it prints twice in my WPF Textbox. I want to make it null for later Dequeue value.

public class NewData
    {
        public int seq;
        public int data;

        public NewData() 
        {

        }

        public NewData(int seq, int data)
        {
            this.seq = seq;
            this.data = data;
        }
    }
private void Thread1()
{
    while (true)
    {
            for (int i = 1; i <= threadRunningTime / threadSleep; i  )
            {
                NewData newData = new NewData(i, random.Next(100));
                thread1_mutex.WaitOne();
                queue.Enqueue(newData);
                thread1_mutex.ReleaseMutex();
                Thread.Sleep(threadSleep);
            }
    }
}
   private void Thread2()
{
    while (true)
    {
        NewData newData = new NewData();

        thread2_mutex.WaitOne();
        if (queue.Count != 0)
        {
            newData = queue.Dequeue();
        }
        else
        {
            newData = null;
        }
        thread2_mutex.ReleaseMutex();
        Thread.Sleep(threadSleep);
    }
}
   
private void Thread3()
{
    while (true)
    {
        NewData newData = new NewData();

        thread2_mutex.WaitOne();
        if (queue.Count != 0)
        {
            newData = queue.Dequeue();
        }
        else
        {
            newData = null;
        }
        thread2_mutex.ReleaseMutex();
        Thread.Sleep(threadSleep);
    }
}

CodePudding user response:

When i use same mutex in Thread 1,2,3 it works fine. What is difference between using same mutex in Thread 1,2,3 and thread1_mutex for Thread1, thread2_mutex for Thread 2,3?

The difference is that using different mutexes would allow one thread to enqueue an item at the same time another thread dequeues an item. Since the Queue class is not thread safe this is not allowed, and just about anything may happen if you do this. You must use a single mutex to prevent concurrent access, with the exception of concurrent read only access. But both enqueue and dequeue needs to write things, so that is not relevant in this case.

How to prevent dequeue (Thread 2 and 3) working twice for same value? if dequeue works twice for same value, it prints twice in my WPF Textbox. I want to make it null for later Dequeue value.

I would assume this is due to the issue above. If only a single thread has exclusive access to the queue you should not be getting duplicates. Note that any updates of the UI must be done from the UI thread. So if you are reading values from multiple threads you will need a thread safe way to hand these values over to the UI thread for display. In some sense, console programs may be easier to use for demonstration, since Console.WriteLine is thread safe.

I would also recommend using the lock statement instead of mutex. The former is both easier to use and should perform better. The only real use case I know for mutex is to provide synchronization across multiple processes, and that is a fairly rare thing to do. Ofcource, even better would be to use a concurrentQueue, but I'm assume that goes against the spirit of the assignment. Note that "mutex" may be used either as an abstract concept, i.e. to provide exclusive access to a resource, or to the specific mutex class in .net. So there may be some confusion about the terms used.

CodePudding user response:

When Thread3 wins the race and calls Mutex.WaitOne before Thread2, then Thread2 must wait until Thread3 has released the mutex by calling Mutex.ReleaseMutex.
If Thread3 has finally released the mutex, Thread2 will be able to continue execution.
This is called a mutual exclusive (short mutex) lock or synchronization mechanism. If you had used a dedicated mutex for each thread, then the threads won't be able to lock each other out and therefore both threads can access the shared resource at the same time (concurrently).
You need at least two participants for a mutual relationship.

In other words: if you want to synchronize access to a shared resource e.g., a Queue, in order to prevent undefined behavior like the dequeuing of the same element by different threads, all the accessing threads must be using the same mutex instance in order to be able lock each other out (mutually). That's the essence of synchronization.

Each mutex instance represents a new waiting queue for the threads.
If multiple threads share the same resource, they must also share the same waiting queue.
This is true for every synchronization mechanism.

  • Related