我可以使用非原子布尔值来同步两个线程之间的共享向量,其中一个线程正在读取,另一个线程正在写入?

问题描述 投票:0回答:2

我正在创建一个快速同步模型来在两个线程之间共享消息队列。我正在查看一个包含一个向量、一个互斥体和一个脏标志的类,如下所示。

#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. 脏标志保证一次只能由一个线程写入,因为所有写入都在锁后面的原子部分内。

  2. 虽然在附加向量(第 1 步)之前脏标志可能被设置为 true(write() 中的第 2 步),但由于 CPU 指令重新排序,这应该不是问题,因为 Consumer() 线程必须等到锁由 write() 线程释放。

  3. 根据 x86 上的缓存一致性协议(我认为是 MESI 或 MOESI),一旦写入脏标志,write() 线程就应该使其无效。

有人能告诉我这个实现是否实际上是线程安全的,或者让我知道这是否有任何缺陷?我避免将脏标志设置为原子,因为这导致了我试图避免的显着减慢。

c++ multithreading queue locking atomic
2个回答
0
投票

在您的情况下,否,因为您的读取正在以不同步的方式访问可变共享内存。您必须使用类似

std::atomic<bool>
之类的内容来访问 tbreadsafe。

如果您希望在没有数据时让读取线程空闲,您也可以看看

std::condition_variable


-2
投票

是的,

std::mutex
保证您的实现是线程安全的

© www.soinside.com 2019 - 2024. All rights reserved.