C# WPF,队列的多线程

C# WPF, Multi-Threads for Queue

Thread1 执行 Enqueue() 线程 2、3 执行 Dequeue()

线程 2、3 具有相同的互斥锁,当我使用不同的互斥锁时,有时会出队两次。

  1. 当我在线程 1、2、3 中使用相同的互斥锁时,它工作正常。在线程 1、2、3 中使用相同的互斥体与线程 1 使用 thread1_mutex、线程 2、3 使用 thread2_mutex 有什么区别?

  2. 如何防止出队(线程 2 和 3)为相同的值工作两次? 如果 dequeue 对相同的值工作两次,它会在我的 WPF 文本框中打印两次。我想让它为以后的出队值设置为 null。

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);
    }
}

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?

不同之处在于,使用不同的互斥体将允许一个线程将一个项目入队,同时另一个线程将一个项目出队。由于 Queue class 不是线程安全的,这是不允许的,如果您这样做,几乎任何事情都可能发生。您必须使用单个互斥锁来防止并发访问,并发只读访问除外。但是enqueue和dequeue都需要写东西,所以在本例中是不相关的。

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.

我认为这是由于上述问题造成的。如果只有一个线程对队列具有独占访问权限,则不应重复。请注意,UI 的任何更新都必须从 UI 线程完成。因此,如果您从多个线程读取值,您将需要一种线程安全的方式将这些值交给 UI 线程进行显示。从某种意义上说,控制台程序可能更容易用于演示,因为 Console.WriteLine 是线程安全的。

我还建议使用 lock 语句而不是互斥锁。前者更易于使用,而且性能应该更好。我所知道的互斥量的唯一实际用例是提供跨多个进程的同步,这是一件相当罕见的事情。当然,更好的方法是使用并发队列,但我认为这违背了任务的精神。请注意,“mutex”既可以用作抽象概念,即提供对资源的独占访问,也可以用作 .net 中的特定互斥 class。所以可能对使用的术语有些混淆。

Thread3 赢得比赛并在 Thread2 之前调用 Mutex.WaitOne 时,则 Thread2 必须等到 Thread3 通过调用 Mutex.ReleaseMutex.
释放互斥量 如果Thread3最终释放了互斥量,Thread2将能够继续执行。
这称为 互斥(简称 互斥)锁或同步机制。 如果您为每个线程使用专用互斥锁,那么线程将无法相互锁定,因此两个线程可以同时(并发)访问共享资源。
您至少需要两个参与者才能建立相互关系。

换句话说:如果您想同步访问共享资源,例如 Queue,为了防止未定义的行为,例如不同线程对同一元素的出列,所有访问线程必须使用相同的互斥锁实例以便能够(相互)锁定彼此。这就是同步的本质。

每个互斥锁实例代表一个新的线程等待队列。
如果多个线程共享同一个资源,那么它们也必须共享同一个等待队列。
每个同步机制都是如此。