【问题标题】:std::atomic_flag and std::lock_guardstd::atomic_flag 和 std::lock_guard
【发布时间】:2017-09-18 15:54:54
【问题描述】:

由于std::lock_guard 不适用于std::atomic_flag,我已经实现了自己的版本:

class atomic_guard {
public:
    inline atomic_guard(std::atomic_flag& lock) : lock(lock) {
        while (this->lock.test_and_set()) {
            /* spin */ 
        };
    };

    inline ~atomic_guard() {
        this->lock.clear();
    };

private:
    std::atomic_flag& lock;
};

这似乎工作正常。问题是:这是为std::atomic_flag 实施 RAII 的正确方法吗?还有一个内置的防护装置吗?如果不是,为什么?专业化std::lock_guard<std::atomic_flag> 看起来很自然。

【问题讨论】:

    标签: c++11 locking atomic


    【解决方案1】:

    您将atomic_guard 用作独立的互斥体类似物是正确的,如果有点不寻常的话。

    无法直接将std::atomic_flagstd::lock_guard 一起使用,因为std::lock_guard 模板管理互斥体,而std::atomic_flag 是(低级)原子布尔类型。

    可以与std::lock_guard 一起使用的互斥体实现必须提供成员函数lockunlock,并且可以这样实现:

    class my_mutex {
        std::atomic_flag flag{ATOMIC_FLAG_INIT};
    
    public:
        void lock()
        {
            while (flag.test_and_set());
        }
    
        void unlock()
        {
            flag.clear();
        }
    };
    

    请注意,这是一个非常基本且效率低下的互斥锁实现,但它与std::lock_guard 兼容:

    my_mutex mtx;
    
    std::lock_guard<my_mutex> lck{mtx};
    

    【讨论】:

    • inefficient 是什么意思? atomic_flag 不是比标准互斥锁更有效吗?至少在某些情况下,例如当锁定时间应该很短时。
    • @freakish 如果一个线程正在等待使用my_mutex 获取锁,那么它正在浪费大量CPU 时间,因为它正处于繁忙的while 循环中
    • 我不会称之为“浪费”。您获得了执行时间,因此这是一种权衡。似乎 atomic_flag 甚至可以比标准互斥锁快约 50 倍。因此,如果您锁定一小段时间,那么“浪费”这些 CPU 周期可能是值得的。这是基准:arangodb.com/2015/02/comparing-atomic-mutex-rwlocks 当然我会在我的场景中进行适当的测试,但我确实希望至少有 2 倍的加速。
    • 但我确实喜欢你的my_mutex 实现。我不知道您可以将std::lock_guard 与自定义类一起使用(而且非常简单)。太好了。
    • @freakish 我已经与std::mutex 进行了一些性能比较(在lock_guard 中易于替换)。通常标准库互斥锁会胜出。显然,实施更先进。我相信它也会在执行上下文切换之前循环一小段时间
    猜你喜欢
    • 1970-01-01
    • 2022-11-22
    • 1970-01-01
    • 1970-01-01
    • 2013-12-29
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多