C# WPF,队列的多线程
C# WPF, Multi-Threads for Queue
Thread1 执行 Enqueue()
线程 2、3 执行 Dequeue()
线程 2、3 具有相同的互斥锁,当我使用不同的互斥锁时,有时会出队两次。
当我在线程 1、2、3 中使用相同的互斥锁时,它工作正常。在线程 1、2、3 中使用相同的互斥体与线程 1 使用 thread1_mutex、线程 2、3 使用 thread2_mutex 有什么区别?
如何防止出队(线程 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
,为了防止未定义的行为,例如不同线程对同一元素的出列,所有访问线程必须使用相同的互斥锁实例以便能够(相互)锁定彼此。这就是同步的本质。
每个互斥锁实例代表一个新的线程等待队列。
如果多个线程共享同一个资源,那么它们也必须共享同一个等待队列。
每个同步机制都是如此。
Thread1 执行 Enqueue() 线程 2、3 执行 Dequeue()
线程 2、3 具有相同的互斥锁,当我使用不同的互斥锁时,有时会出队两次。
当我在线程 1、2、3 中使用相同的互斥锁时,它工作正常。在线程 1、2、3 中使用相同的互斥体与线程 1 使用 thread1_mutex、线程 2、3 使用 thread2_mutex 有什么区别?
如何防止出队(线程 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
,为了防止未定义的行为,例如不同线程对同一元素的出列,所有访问线程必须使用相同的互斥锁实例以便能够(相互)锁定彼此。这就是同步的本质。
每个互斥锁实例代表一个新的线程等待队列。
如果多个线程共享同一个资源,那么它们也必须共享同一个等待队列。
每个同步机制都是如此。