在 C++ 中,没有直接类似于 C# 的 AutoResetEvent
和 ManualResetEvent
的类,但可以通过一些线程同步机制来实现类似的功能。C++ 提供了一些线程同步原语,如 std::condition_variable
和 std::mutex
,这些可以用来模拟类似于 C# 中 AutoResetEvent
和 ManualResetEvent
的行为。
AutoResetEvent
和 ManualResetEvent
的基本区别
AutoResetEvent
:每次信号被设置后,它只能唤醒一个等待线程,且会自动重置为未信号状态。ManualResetEvent
:每次信号被设置后,它会保持信号状态,直到被显式重置,所有等待线程都会被唤醒。
C++ 中的替代方案
1. 使用 std::condition_variable
来实现 AutoResetEvent
在 C++ 中,std::condition_variable
可以用来模拟类似于 AutoResetEvent
的行为。std::condition_variable
会让线程在某个条件上等待,当条件满足时,通知一个或所有等待的线程继续执行。
#include <iostream>
#include <thread>
#include <mutex>
#include <condition_variable>
#include <chrono>class AutoResetEvent {
public:AutoResetEvent(bool initial_state = false): signaled(initial_state) {}// 唤醒一个线程void Set() {std::lock_guard<std::mutex> lock(mutex_);signaled = true;cv_.notify_one(); // 唤醒一个等待线程}// 等待线程被唤醒void Wait() {std::unique_lock<std::mutex> lock(mutex_);cv_.wait(lock, [this]() { return signaled; }); // 等待直到 signaled 为 truesignaled = false; // 唤醒后自动重置为未信号状态}private:bool signaled; // 是否处于信号状态std::mutex mutex_;std::condition_variable cv_;
};void ThreadA(AutoResetEvent& are)
{std::cout << "线程A开始等待...\n";are.Wait();std::cout << "线程A被唤醒,继续执行\n";
}void ThreadB(AutoResetEvent& are)
{std::this_thread::sleep_for(std::chrono::seconds(2));std::cout << "线程B设置信号\n";are.Set();
}int main() {AutoResetEvent are;std::thread t1(ThreadA, std::ref(are)); // 线程A等待std::thread t2(ThreadB, std::ref(are)); // 线程B设置信号t1.join();t2.join();return 0;
}
代码说明:
AutoResetEvent
类:封装了std::condition_variable
和std::mutex
,并通过一个布尔变量signaled
来标记是否处于信号状态。调用Set()
方法时会唤醒一个等待线程,调用Wait()
方法时会让当前线程等待信号。Wait()
:当signaled
为true
时,线程会被唤醒,并且signaled
会自动重置为false
,就像AutoResetEvent
的行为。
2. 使用 std::condition_variable
和 std::atomic<bool>
来实现 ManualResetEvent
与 AutoResetEvent
类似,ManualResetEvent
会在 Set()
后保持信号状态,直到调用 Reset()
。可以通过使用 std::atomic<bool>
来维护信号状态,这样可以使多个线程在 Set()
后被唤醒。
#include <iostream>
#include <thread>
#include <mutex>
#include <condition_variable>
#include <atomic>
#include <chrono>class ManualResetEvent {
public:ManualResetEvent(bool initial_state = false): signaled(initial_state) {}// 唤醒所有等待线程void Set() {std::lock_guard<std::mutex> lock(mutex_);signaled = true;cv_.notify_all(); // 唤醒所有等待线程}// 重置为未信号状态void Reset() {std::lock_guard<std::mutex> lock(mutex_);signaled = false;}// 等待线程被唤醒void Wait() {std::unique_lock<std::mutex> lock(mutex_);cv_.wait(lock, [this]() { return signaled; }); // 等待直到 signaled 为 true}private:std::atomic<bool> signaled; // 信号状态std::mutex mutex_;std::condition_variable cv_;
};void ThreadA(ManualResetEvent& mre)
{std::cout << "线程A开始等待...\n";mre.Wait();std::cout << "线程A被唤醒,继续执行\n";
}void ThreadB(ManualResetEvent& mre)
{std::this_thread::sleep_for(std::chrono::seconds(2));std::cout << "线程B设置信号\n";mre.Set(); // 设置信号
}int main() {ManualResetEvent mre;std::thread t1(ThreadA, std::ref(mre)); // 线程A等待std::thread t2(ThreadB, std::ref(mre)); // 线程B设置信号t1.join();t2.join();return 0;
}
代码说明:
ManualResetEvent
类:使用std::atomic<bool>
来保持信号状态,Set()
会将状态设置为true
并唤醒所有等待的线程,Reset()
会将状态重置为false
。Set()
:设置信号状态并唤醒所有等待的线程。Wait()
:等待直到信号状态为true
。Reset()
:手动重置信号状态,使得线程再次进入等待状态。
总结
AutoResetEvent
可以通过std::condition_variable
和一个布尔标志来模拟,调用Wait()
会让线程等待信号,Set()
会唤醒一个线程并自动重置信号状态。ManualResetEvent
可以通过std::condition_variable
和std::atomic<bool>
来模拟,Set()
会保持信号状态,直到显式调用Reset()
重置状态。
这些 C++ 代码示例演示了如何利用 std::condition_variable
和 std::mutex
来实现类似于 C# 中的 AutoResetEvent
和 ManualResetEvent
的功能。