在 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 会让线程在某个条件上等待,当条件满足时,通知一个或所有等待的线程继续执行。
            
            
              cpp
              
              
            
          
          #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 为 true
        signaled = 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() 后被唤醒。
            
            
              cpp
              
              
            
          
          #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 的功能。