防止 C++ 中的交错

Posted

技术标签:

【中文标题】防止 C++ 中的交错【英文标题】:Preventing interleaving in C++ 【发布时间】:2014-08-18 18:25:43 【问题描述】:

考虑以下示例类,它允许一个线程等待来自另一个线程的信号。

class Sync

    std::mutex mtx, access;
    std::condition_variable cv;
    bool waiting;

public:
    Sync()
        : waiting(false)
    
    
    Sync(const Sync&);
    ~Sync()
    
        sendSignal();
    

    void waitForSignal()
    
        access.lock();
        if (!waiting)
        
            std::unique_lock<std::mutex> lck (mtx);
            waiting = true;
            access.unlock();

            // in the time between these two statements, 'sendSignal()' acquires 
            // the lock and calls 'cv.notify_all()', thus the signal was missed. 

            cv.wait(lck);
        
        else
            access.unlock();
    
    void sendSignal()
    
        access.lock();
        if (waiting)
        
            std::unique_lock<std::mutex> lck (mtx);
            cv.notify_all();
            waiting = false;
        
        access.unlock();
    
;

我遇到的问题是,在解锁“access”互斥锁和在 condition_variable 上调用“wait()”之间的时间间隔内,有时会因为交错而丢失信号。我怎样才能防止这种情况发生?

【问题讨论】:

看起来你需要一个条件变量 我正在使用条件变量。 关键区域的堆栈溢出可能会有所帮助。 ***.com/questions/4434050/… @MadisonBrown 这个answer 提供了一个使用条件变量的信号量代理的合理实现。我认为 boost 的东西可以很容易地映射到适当的 c++11 特性。 您通常不想等待来自另一个线程的“信号”或任何其他瞬时事件——正是因为这样的事件很容易被错过。相反,您希望等待某些条件变为真(例如“数据可供读取”)。你检查条件,只有当它是假的时候才等待。然后,来自另一个线程的信号只是让您醒来并再次检查条件的一种手段。条件变量巧妙地封装了这种模式。 【参考方案1】:

您可能应该只有一个互斥锁。我不明白您为什么需要访问权限。使用 mtx 保护 waiting 变量和条件变量。

类同步 std::mutex mtx; std::condition_variable 简历; 布尔等待; 上市: 同步() :等待(假) 同步(常量同步&); 〜同步() 发送信号(); 无效的等待信号() std::unique_lock lck (mtx); 如果(!等待) 等待=真; cv.wait(lck); 无效的发送信号() std::unique_lock lck (mtx); 如果(等待) cv.notify_all(); 等待=假; ;

waiting 变量和条件变量 state 绑定在一起,因此应将它们视为单个临界区。

【讨论】:

以上是关于防止 C++ 中的交错的主要内容,如果未能解决你的问题,请参考以下文章

防止 C++ 中的虚拟方法实现

防止 C++ 中的意外对象复制

c++ 防止类共享静态对象

c ++防止通过getter更改引用

ALSA:防止扬声器欠载的方法

C ++中的仿函数以防止重复?