我正在创建一个快速同步模型来在两个线程之间共享消息队列。我正在查看一个包含一个向量、一个互斥体和一个脏标志的类,如下所示。
#include <vector>
#include <mutex>
class SharedVector {
std::mutex vector_lock;
std::vector<int> vec;
volatile bool dirty = false;
void write(int a) {
std::unique_lock lock(vector_lock);
vector.push_back(a); // Step 1
dirty = true; // Step 2
}
void consume(std::vector<int>& container) {
if (dirty) {
std::unique_lock lock(vector_lock);
container = std::move(vec); // Invalidates original vec
dirty = false;
}
}
};
我假设这个实现是线程安全的,即使脏标志是在锁之外读取的,但我不确定。这背后的原因是
脏标志保证一次只能由一个线程写入,因为所有写入都在锁后面的原子部分内。
虽然在附加向量(第 1 步)之前脏标志可能被设置为 true(write() 中的第 2 步),但由于 CPU 指令重新排序,这应该不是问题,因为 Consumer() 线程必须等到锁由 write() 线程释放。
根据 x86 上的缓存一致性协议(我认为是 MESI 或 MOESI),一旦写入脏标志,write() 线程就应该使其无效。
有人能告诉我这个实现是否实际上是线程安全的,或者让我知道这是否有任何缺陷?我避免将脏标志设置为原子,因为这导致了我试图避免的显着减慢。
在您的情况下,否,因为您的读取正在以不同步的方式访问可变共享内存。您必须使用类似
std::atomic<bool>
之类的内容来访问 tbreadsafe。
如果您希望在没有数据时让读取线程空闲,您也可以看看
std::condition_variable
。
是的,
std::mutex
保证您的实现是线程安全的