【问题标题】:shared data between threads synchronized using std::atomic使用 std::atomic 同步的线程之间的共享数据
【发布时间】:2015-03-12 15:55:26
【问题描述】:

我有生产者和消费者线程,各 1 个。两者都必须共享一些数据(可以是一些用户定义的类的对象)。我想使用 c++ 11 std::atomic 来同步访问,这样如果消费者在生产者写入共享数据时读取,消费者会等待生产者完成。

如果下面的代码可以实现这一点,请查看代码并提供您的 cmets。你可以假设生产者和消费者线程正在调用 set 并获取 SharedData 类的对象,该对象是用一些数据对象初始化的。

感谢您的宝贵时间和宝贵意见。

template <typename T>
class SharedData
{
    static const int SD_BUSY = 0x01;
    static const int SD_FREE = 0x02;
    typedef std::atomic<int> AtomicInt;

    struct AcqRel
    {
        AtomicInt& _atomInt;
        AcqRel(AtomicInt& atomInt) :_atomInt(atomInt)
        {
            int expectedValue = SharedData::SD_FREE;
            do
            {
                expectedValue = SharedData::SD_FREE;
            } while (!_atomInt.compare_exchange_strong(expectedValue, SharedData::SD_BUSY));
        }

        ~AcqRel()
        {
            _atomInt.store(SharedData::SD_FREE);
        }
    };

    AtomicInt _atomInt = SD_FREE;
    T _data;

public:
    void set(T& data)
    {
        AcqRel al(_atomInt);
        _data = data;
    }

    void get(T& data)
    {
        AcqRel al(_atomInt);
        data = _data;
    }
};

请建议一种无锁方法来实现我上面尝试的内容。我想通过某种无锁方法在线程之间共享数据。

【问题讨论】:

  • 为什么要使用 std::atomic 而不是 std::mutex 来实现互斥?像这样的幼稚自旋锁实现在竞争中具有可怕的行为。
  • std::atomic 不是强制性的,但任何其他无锁方法都可以。我知道 std::mutex 更适合这个要求,但我不想使用锁。您能否提出更好的方法或指出我的实施中的错误。
  • 来自 Stroustrup 的“C++ 编程语言”:除了简单的计数器等之外,更喜欢互斥锁而不是原子。
  • 你的核心do/while 循环犯了两个巨大的错误。首先,它可能会占用资源,使某些 CPU 上的 FSB 饱和,并使某些 CPU 上的物理内核中的其他线程处于饥饿状态。这很可怕,因为它会使需要释放的线程饿死!其次,当你最终确实获得时,并且尽可能快地运行以释放至关重要,你会采用最糟糕的可想象的错误预测分支并基本上破坏管道。坦率地说,在这段代码的设计中似乎没有真正考虑到性能。

标签: multithreading c++11 atomic


【解决方案1】:

实现看起来是正确的,这意味着它没有数据竞争并且提供了所需的数据保护。但正如凯西已经评论的那样,您有效地尝试模仿互斥体行为。而且您的实施效率较低,因此没有必要这样做。毕竟,尽管名称为 AcqRel,但该类实际上使用了默认的 memory_seq_cst 语义。最好在这里真正使用获取/释放(虽然std::mutex 更好)。

【讨论】:

  • 说我使用了默认的memory_seq_cst,你的意思是它实际上是在内部使用操作系统互斥对象吗??
  • @anandsrivastava 不,使用memory_seq_cst 是关于内存一致性,即围绕原子对象的语句的一致顺序。
  • @anandsrivastava 该标准允许std::atomic 的实现使用底层互斥锁。您可以使用std::atomic::is_lock_free 检查std::atomic 是否实现无锁。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-06-28
  • 1970-01-01
  • 1970-01-01
  • 2023-03-25
  • 1970-01-01
相关资源
最近更新 更多