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