排队进行全局锁定的多个线程应该在获得第一次锁定后返回true

时间:2011-03-29 14:48:23

标签: c++ multithreading boost synchronization

类似的问题是这个:Are threads waiting on a lock FIFO?但是,在这个问题中,一旦获得锁只有一个线程执行受保护的代码,最后所有线程都会执行代码。

我想要做的是执行一次受保护的代码,但是对于当时排队等待方法调用的所有线程,返回true。

基本上,受保护的代码是一个全局检查点,它与当时等待的所有线程相关。即,连续N个检查点不会超过1个。

请注意,在完成检查点操作时,会对该方法进行其他调用,这些调用本身需要一个新的检查点调用。

我相信我想做的是“批量”同步调用全局函数。

如何在C ++中实现这一点,也许使用Boost?

3 个答案:

答案 0 :(得分:1)

您似乎在寻找try_lock()

给定一些Boost.Thread Lockable,如果Lockable::try_lock()可以在那一刻获得锁定,则对bool的调用将返回true,否则如果无法获取锁定则返回false。

当您的线程到达检查点时,让它尝试获取此锁定。如果失败,则该函数中已存在另一个线程。如果成功,请检查一些bool以查看检查点是否已经运行。如果已运行,请释放锁定并继续。如果尚未运行,请保持锁定并运行检查点功能并将检查点{{1}}设置为true。

答案 1 :(得分:1)

您似乎想要的内容看起来像boost提供的屏障。但是,如果这对您没有帮助,您可以在boost

中使用条件变量

答案 2 :(得分:0)

这是我将如何做的伪代码。我假设现有mutex课程,其中包含lock()unlock()次操作。

// This forward declaration helps with declaration
// of the "friend" status for the nested class.
class DoItOnce;

class DoItOnce
{
private:
    bool    m_amFirst;
    mutex   m_mutex;
    friend class ::DoItOnce::Op;    
public:
    DoItOnce()
    {
        m_amFirst = true;
        init(m_mutex);
    }
    ~DoItOnce() { destroy(m_mutex); }
    void reset()
    {
        m_mutex.lock();
        m_amFirst = true;
        m_mutex.lock();
    }

    //--------
    // Nested class
    //--------
    class Op {
    public:
        Op(DoItOnce & sync)
            : m_sync(sync)
        {
            m_sync.m_mutex.lock();
            m_amFirst = m_sync.m_amFirst;
            m_sync.m_amFirst = false;
        }
        ~Op() { m_sync.m_mutex.unlock(); }
        bool amFirst() { return m_amFirst; }
    private:
        DoItOnce &  m_sync;
        bool        m_amFirst;
    }; // end of nested class
}; // end of outer class

以下是一个说明其预期用途的示例。您将实现doWork()操作并让所有线程调用它。

class WorkToBeDoneOnce
{
private:
    DoItOnce    m_sync;    
public:
    bool doWork()
    {
        DoItOnce::Op    scopedLock(m_sync);

        if (!scopedLock.amFirst()) {
            // The work has already been done.
            return true;
        }
        ... // Do the work
        return true;
    }
    void resetAmFirstFlag()
    {
        m_sync.reset();
    }
}

如果您对我使用DoItOnce::Op嵌套类感到困惑,那么您可以在我的通用同步策略文件中找到对此编码习惯用语的解释,该文件可用{{3各种格式(HTML,PDF和幻灯片)。