我知道如何使用LOCK线程安全地增加一个值:
lock inc [J];
Run Code Online (Sandbox Code Playgroud)
但是我如何以线程安全的方式阅读[J](或任何值)?LOCK前缀不能与mov一起使用.如果我做以下事情:
xor eax, eax;
lock add eax, [J];
mov [JC], eax;
Run Code Online (Sandbox Code Playgroud)
它在第2行引发错误.
我知道如何在x86 ASM中自动写入一个值.但我怎么读一个?LOCK前缀不能与mov一起使用.
为了增加价值,我正在做:
lock inc dword ptr Counter
Run Code Online (Sandbox Code Playgroud)
如何以线程安全的方式读取Counter?
你将如何在x86中实现128位原子操作?
英特尔系统编程指南,第1部分,8.1锁定原子操作指定保证16位,32位和64位原子操作.那么,你能用2个带有LOCK前缀的64位操作来实现128位原子操作吗?就像是...
LOCK mov 64bits->addr
LOCK mov 64bits->addr+64bits
Run Code Online (Sandbox Code Playgroud)
显然,SSE具有128位XMM寄存器.你能用这些寄存器进行128位比较和交换吗?
考虑以下代码:
#include <atomic>
int main(void) {
std::atomic<double> aDouble;
aDouble = 6.0;
}
Run Code Online (Sandbox Code Playgroud)
G ++编译它就好了,而clang ++产生以下内容:
clang++ -std=c++11 Main.cpp
/tmp/Main-d4f0fc.o: In function `std::atomic<double>::store(double, std::memory_order)':
Main.cpp:(.text._ZNSt6atomicIdE5storeEdSt12memory_order[_ZNSt6atomicIdE5storeEdSt12memory_order]+0x31): undefined reference to `__atomic_store_8'
clang: error: linker command failed with exit code 1 (use -v to see invocation)
Run Code Online (Sandbox Code Playgroud)
他们没有链接到相同的标准库吗?
使用atomic_store存储的数据和使用atomic_load加载的数据是否总是一致?
具体来说:C11程序访问故意放置在现代Intel CPU上高速缓存行之间边界的64位数据.它使用atomic_store和atomic_load(from <stdatomic.h>)从多个线程(在不同的核心上运行)访问此数据.
数据是否总是显得一致,或者加载它(atomic_load)有时会有一些属于旧值的字节,以及属于更新值的其他字节?
以下是基本的结构和变量定义以及程序的有趣部分,它们在一个循环中,并行地从多个线程发生:
struct Data {
uint8_t bytes[CACHELINE__BYTECOUNT - 4];
atomic_uint_fast64_t u64;
} __attribute__((packed)) __attribute__((aligned ((CACHELINE__BYTECOUNT))));
#define VAL1 (0x1111111111111111)
#define VAL2 (0xFFFFFFFFFFFFFFFF)
static struct Data data = { .u64 = VAL1 };
...
for (uint32_t j = 0; j < 1000; j++) {
atomic_store(&data.u64, VAL1);
atomic_store(&data.u64, VAL2);
}
const uint64_t val = atomic_load(&data.u64);
/* is 'val' always VAL1 or VAL2? */
Run Code Online (Sandbox Code Playgroud)
(完全可运行的程序:https://gist.github.com/sinelaw/1230d4675d6a4fff394110f17e463954)
用gcc 6.3.0和clang 3.7检查它显示它不是原子的:
$ clang -std=c11 -Wall -Wextra /tmp/atomic.c -o …Run Code Online (Sandbox Code Playgroud) 由于std::atomic::is_lock_free()可能没有真正反映现实[ 参考 ],我正在考虑编写一个真正的运行时测试.然而,当我开始研究它时,我发现这不是一个我认为不可能完成的微不足道的任务.我想知道是否有一些聪明的想法可以做到这一点.
我知道在 C++ 中赋值可能不是原子的。我试图触发竞争条件来显示这一点。
但是我下面的代码似乎没有触发任何这样的。如何更改它以使其最终触发竞争条件?
#include <iostream>
#include <thread>
volatile uint64_t sharedValue = 1;
const uint64_t value1 = 13;
const uint64_t value2 = 1414;
void write() {
bool even = true;
for (;;) {
uint64_t value;
if (even)
value = value1;
else
value = value2;
sharedValue = value;
even = !even;
}
}
void read() {
for (;;) {
uint64_t value = sharedValue;
if (value != value1 && value != value2) {
std::cout << "Race condition! Value: " << value << …Run Code Online (Sandbox Code Playgroud) 考虑下面的示例是打算等到另一个线程存储42在一个共享变量shared没有锁,无需等待线程终止,为什么会volatile T或std::atomic<T>会要求或建议,以保证并发正确性?
#include <atomic>
#include <cassert>
#include <cstdint>
#include <thread>
int main()
{
int64_t shared = 0;
std::thread thread([&shared]() {
shared = 42;
});
while (shared != 42) {
}
assert(shared == 42);
thread.join();
return 0;
}
Run Code Online (Sandbox Code Playgroud)
使用 GCC 4.8.5 和默认选项,示例按预期工作。
我正在实现一个基于此算法的无锁队列,该算法使用计数器来解决ABA问题.但我不知道如何用c ++ 11 CAS实现这个计数器.例如,从算法:
E9: if CAS(&tail.ptr->next, next, <node, next.count+1>)
Run Code Online (Sandbox Code Playgroud)
它是一个原子操作,意思是如果tail.ptr->next等于next,则tail.ptr->next指向node并同时(原子地)产生next.count+1.但是,使用C++ 11 CAS,我只能实现:
std::atomic_compare_exchange_weak(&tail.ptr->next, next, node);
Run Code Online (Sandbox Code Playgroud)
这不可能next.count+1同时发生.
在这里(以及一些SO问题)我看到C++不支持像无锁的东西,std::atomic<double>并且还不能支持像原子AVX/SSE向量这样的东西,因为它依赖于CPU(虽然现在我知道CPU,ARM, AArch64和x86_64有矢量).
但是double在x86_64中对s或向量的原子操作是否有汇编级支持?如果是这样,支持哪些操作(如加载,存储,添加,减去,可能相乘)?MSVC++ 2017实现哪些操作无锁atomic<double>?