许多读/一写原子变量

时间:2015-05-06 10:06:30

标签: c++ multithreading

你能帮帮我吗?

假设我有p-1个读线程和一个写线程。它们都在一个原子int变量中读写。可能是如果所有的读写同时发生,写操作会等待p - 1次吗?我有疑问,因为当原子操作发生时,有一些奇怪的锁(在汇编程序中),我担心它会锁定内存(变量是)。因此,写操作可能会等待p-1读取。会发生吗?

以下是一些简单的代码:

#include <atomic>
#include <iostream>
#include <thread>
#include <vector>


std::atomic<int> val;

void writer()
{
    val.store(7);
}

void read()
{
    int tmp = val.load();

    while (tmp == 0)
    {
        std::cout << std::this_thread::get_id() << ": wait" << std::endl;
        tmp = val.load();
    }

    std::cout << std::this_thread::get_id() << " Operation: " << tmp * tmp << std::endl;
}

int main()
{
    val.store(0);

    std::vector<std::thread> v;

    for (int i = 0; i < 1; ++i)
        v.push_back(std::thread(read));

    std::this_thread::sleep_for(std::chrono::milliseconds(77));

    writer();

    std::for_each(v.begin(), v.end(), std::mem_fn(&std::thread::join));

    return 0;
}

谢谢!

1 个答案:

答案 0 :(得分:3)

  1. 处理器的指令,锁定内存总线(具有LOCK前缀),不会在通常的高级别中使用锁定。它使线程(调用一个,可能是一些访问相同或接近内存块的并发线程)稍慢。 此的上限仅取决于计算机及其体系结构。 正常锁也会使线程变慢,但这种较慢的数量在很大程度上取决于锁争用,锁定实现属性(例如,公平性)和锁保护下的代码。 除了因性能原因之外,你不应该为锁定内存访问而烦恼。

  2. 实际上,LOCK前缀不需要原子加载/存储。我想,这是一个编译器优化,它提供顺序一致的内存顺序。默认情况下,此命令由.store().load()原子的方法强制执行,但在您的示例中不需要。最常用的模式是:

    • 使用放宽内存顺序进行初始化:

      val.store(0, std::memory_order_relaxed);
      
    • 使用获取内存顺序以获取读取值:

      tmp = val.load(std::memory_order_acquire);
      
    • 使用发布内存顺序写入(更改)值:

      val.store(7, std::memory_order_release);
      

    这将阻止编译器使用带有LOCK前缀的指令。