【发布时间】: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