多线程:我是否需要以只读方法保护我的变量?

Bry*_*hen 7 c++ concurrency multithreading locking c++11

关于使用lock来保护我的共享数据结构,我几乎没有问题.我正在使用C/C++/ObjC/Objc ++

例如,我有一个在多线程环境中使用的计数器类

class MyCounter {
private:
    int counter;
    std::mutex m;

public:
    int getCount() const {
        return counter;
    }
    void increase() {
        std::lock_guard<std::mutex> lk(m);
        counter++;
    }
};
Run Code Online (Sandbox Code Playgroud)
  1. 我是否需要std::lock_guard<std::mutex> lk(m);getCount()方法中使用它来使其线程安全?

  2. 如果只有两个线程会发生什么:读者线程和编写器线程然后我必须保护它吗?因为只有一个线程正在修改变量所以我认为不会发生丢失更新.

  3. 如果共享原始类型变量有多个int编写器/阅读器(例如)如果我只锁定写入方法而不是读取方法,可能会发生什么样的灾难?与64位类型相比,8bits类型会有什么不同吗?

  4. 原始类型是默认的原子吗?例如,写入a char始终是原子的?(我知道这在Java中是正确的,但我不知道c ++,如果平台很重要,我在Mac上使用llvm编译器)

pax*_*blo 7

是的,除非您能保证对基础变量的更改counter是原子的,否则您需要互斥锁.

经典示例,比方说counter是一个双字节值,在(非原子)阶段递增:

(a) add 1 to lower byte
    if lower byte is 0:
(b)     add 1 to upper byte
Run Code Online (Sandbox Code Playgroud)

初始值为255.

如果另一个线程进入低字节更改和高字节更改之间的任何位置,它将读取0而不是正确的255(预增量)或256(后增量).

就哪些数据类型是原子的而言,最新的C++标准在a头文件中定义它们.

如果您没有 C++ 11功能,那么实现哪些类型是原子的.

  • 即使原子,你仍然需要它来确保`counter`的正确可见性,否则你可能会看到旧值.我想如果你看到旧的价值你没事,你会没事的. (4认同)