江门网站建设junke100,深圳小企业网站建设设计制作,长沙网页设计哪家专业,贵州省铜仁市城乡建设局网站使用AutoResetEvent和ManualResetEvent进行线程同步和通信 文章目录 使用AutoResetEvent和ManualResetEvent进行线程同步和通信介绍AutoResetEventManualResetEvent 异同点使用场景和代码示例AutoResetEvent 使用示例ManualResetEvent 使用示例阻塞多个线程并同时激活 介绍
在…
使用AutoResetEvent和ManualResetEvent进行线程同步和通信 文章目录 使用AutoResetEvent和ManualResetEvent进行线程同步和通信介绍AutoResetEventManualResetEvent 异同点使用场景和代码示例AutoResetEvent 使用示例ManualResetEvent 使用示例阻塞多个线程并同时激活 介绍
在多线程编程中AutoResetEvent 和 ManualResetEvent 是两个常用的同步原语。它们用于线程间的通信和协调以确保线程按照特定的顺序执行。本篇博客将介绍这两种同步原语的概念、用法和区别。
AutoResetEvent
AutoResetEvent (自动重置事件)是一个同步基元它允许一个线程等待其他线程在信号状态之前进行等待用于在线程间提供简单的信号通知机制。它的工作方式是当一个线程通过调用 WaitOne() 方法等待事件信号时如果事件处于非终止状态线程将被阻塞。当另一个线程调用 Set() 方法将事件设置为终止状态时等待的线程将被唤醒并且事件将自动重置为非终止状态。
ManualResetEvent
ManualResetEvent (手动重置事件)也是一个同步基元它与AutoResetEvent类似也用于在线程间提供信号通知机制。与 AutoResetEvent 不同的是ManualResetEvent 在设置为终止状态后会一直保持终止状态直到调用 Reset() 方法将其重置为非终止状态。另外它允许所有等待的线程在同一个信号状态下被唤醒。当一个线程通过调用 WaitOne() 方法等待事件信号时如果事件处于非终止状态线程将被阻塞。只有当事件被设置为终止状态时线程才会被唤醒。
异同点
虽然 AutoResetEvent 和 ManualResetEvent 都用于线程间的同步和通信它们之间有以下几个关键的异同点
重置行为AutoResetEvent 在一个等待线程被唤醒后会自动将事件重置为非终止状态而 ManualResetEvent 则需要显式地调用 Reset() 方法将事件重置为非终止状态。信号通知AutoResetEvent 只允许一个等待线程被唤醒即使有多个线程等待而 ManualResetEvent 允许多个等待线程被唤醒。等待过程AutoResetEvent 在一个等待线程被唤醒后其他等待线程仍然会继续等待而 ManualResetEvent 在一个等待线程被唤醒后所有等待线程都会被唤醒。 使用场景和代码示例
根据上述的异同点我们可以根据不同的需求来选择使用 AutoResetEvent 或 ManualResetEvent。
AutoResetEvent 使用示例
我们创建了两个工作线程并使用 AutoResetEvent 来同步它们的执行。在主线程中我们先唤醒第一个等待线程然后等待一段时间再唤醒第二个等待线程。这样每个线程只会被唤醒一次然后自动重置事件继续等待下一个信号。 using System;using System.Threading;class Program{static AutoResetEvent autoResetEvent new AutoResetEvent(false);static void Main(string[] args){Thread thread1 new Thread(Worker);Thread thread2 new Thread(Worker);thread1.Start();thread2.Start();// 唤醒第一个等待线程autoResetEvent.Set();// 唤醒第二个等待线程Thread.Sleep(1000);autoResetEvent.Set();// 等待线程执行完毕thread1.Join();thread2.Join();}static void Worker(){Console.WriteLine(Worker started);autoResetEvent.WaitOne();Console.WriteLine(Worker finished);}}ManualResetEvent 使用示例
我们同样创建了两个工作线程但这次使用ManualResetEvent 来同步它们的执行。在主线程中我们设置了事件为终止状态这将唤醒所有等待线程。由于 ManualResetEvent 保持终止状态每个线程只会被唤醒一次然后继续执行直到结束。 using System;using System.Threading;class Program{static ManualResetEvent manualResetEvent newManualResetEvent(true);static void Main(string[] args){Thread thread1 new Thread(Worker);Thread thread2 new Thread(Worker);thread1.Start();thread2.Start();// 唤醒所有等待线程manualResetEvent.Set();// 等待线程执行完毕thread1.Join();thread2.Join();}static void Worker(){Console.WriteLine(Worker started);manualResetEvent.WaitOne();Console.WriteLine(Worker finished);}}阻塞多个线程并同时激活
如果需要阻塞多个线程并同时激活多个线程建议使用 ManualResetEvent。原因是 ManualResetEvent 允许多个等待线程被唤醒而 AutoResetEvent 只允许一个等待线程被唤醒。
下面是一个使用 ManualResetEvent 的示例代码
using System;
using System.Threading;class Program
{static ManualResetEvent manualResetEvent new ManualResetEvent(false);static void Main(string[] args){Thread[] threads new Thread[5];for (int i 0; i threads.Length; i){threads[i] new Thread(Worker);threads[i].Start();}// 阻塞所有线程Console.WriteLine(Blocking all threads...);manualResetEvent.WaitOne();// 激活所有线程Console.WriteLine(Activating all threads...);manualResetEvent.Set();// 等待线程执行完毕foreach (Thread thread in threads){thread.Join();}}static void Worker(){Console.WriteLine(Worker started);manualResetEvent.WaitOne();Console.WriteLine(Worker finished);}
}在示例中创建了 5 个工作线程并使用 ManualResetEvent 来阻塞和激活这些线程。执行的流程为
主线程将 ManualResetEvent 设置为非终止状态阻塞所有的工作线程主线程打印消息并将 ManualResetEvent 设置为终止状态激活所有的工作线程等待所有线程执行完毕。