相关疑难解决方法(0)

num ++是'int num'的原子吗?

一般地,对于int num,num++(或++num),作为读-修改-写操作中,是不是原子.但我经常看到编译器,例如GCC,为它生成以下代码(在这里尝试):

在此输入图像描述

由于第5行对应于num++一条指令,我们可以得出结论,在这种情况下num++ 是原子的吗?

如果是这样,是否意味着如此生成num++可以在并发(多线程)场景中使用而没有任何数据争用的危险(例如,我们不需要制作它,std::atomic<int>并强加相关成本,因为它是无论如何原子)?

UPDATE

请注意,这个问题不是增量是否原子的(它不是,而且是问题的开头行).它是否可以在特定场景中,即在某些情况下是否可以利用单指令性质来避免lock前缀的开销.而且,作为公认的答案约单处理器的机器,还有部分提到这个答案,在其评论和其他人谈话解释,它可以(尽管不是C或C++).

c c++ assembly multithreading atomic

148
推荐指数
8
解决办法
1万
查看次数

std :: atomic的锁在哪里?

如果数据结构中包含多个元素,则它的原子版本不能(始终)无锁.我被告知这对于较大的类型是正确的,因为CPU不能在不使用某种锁的情况下以原子方式更改数据.

例如:

#include <iostream>
#include <atomic>

struct foo {
    double a;
    double b;
};

std::atomic<foo> var;

int main()
{
    std::cout << var.is_lock_free() << std::endl;
    std::cout << sizeof(foo) << std::endl;
    std::cout << sizeof(var) << std::endl;
}
Run Code Online (Sandbox Code Playgroud)

输出(Linux/gcc)是:

0
16
16
Run Code Online (Sandbox Code Playgroud)

由于原子和foo大小相同,我不认为锁存储在原子中.

我的问题是:
如果一个原子变量使用一个锁,它存储在哪里,这对该变量的多个实例意味着什么?

c++ x86 atomic c++11 stdatomic

67
推荐指数
3
解决办法
4729
查看次数

为什么在x86上对自然对齐的变量进行整数赋值?

我一直在读这篇关于原子操作的文章,它提到了32位整数赋值在x86上是原子的,只要该变量是自然对齐的.

为什么自然对齐确保原子性?

c c++ concurrency x86 atomic

28
推荐指数
2
解决办法
5386
查看次数

真正测试std :: atomic是否无锁

由于std::atomic::is_lock_free()可能没有真正反映现实[ 参考 ],我正在考虑编写一个真正的运行时测试.然而,当我开始研究它时,我发现这不是一个我认为不可能完成的微不足道的任务.我想知道是否有一些聪明的想法可以做到这一点.

c++ concurrency atomic lock-free c++11

6
推荐指数
1
解决办法
968
查看次数

原子清除无符号整数的最低非零位

问题:
我正在寻找清除无符号原子的最低非零位的最佳方法,如std::atomic_uint64_t线程安全方式,而不使用额外的互斥锁等.另外,我还需要知道,哪个位被清除了.

示例: 假设,如果存储的当前值是,0b0110我想知道最低的非零位是位1(0索引)并将变量设置为0b0100.

我想出了最好的版本是这样:

#include <atomic>
#include <cstdint>

inline uint64_t with_lowest_non_zero_cleared(std::uint64_t v){
    return v-1 & v;
}
inline uint64_t only_keep_lowest_non_zero(std::uint64_t v){
    return v & ~with_lowest_non_zero_cleared(v);
}

uint64_t pop_lowest_non_zero(std::atomic_uint64_t& foo)
{
    auto expected = foo.load(std::memory_order_relaxed);
    while(!foo.compare_exchange_weak(expected,with_lowest_non_zero_cleared(expected), std::memory_order_seq_cst, std::memory_order_relaxed))
    {;}
    return only_keep_lowest_non_zero(expected);
}
Run Code Online (Sandbox Code Playgroud)

有更好的解决方案吗?

笔记:

  • 它不一定是最低的非零位 - 我也很满意清除最高位或设置最高/最低"零位"的解决方案,如果这有所不同
  • 我非常喜欢标准的c ++(17)版本,但会接受一个使用内在函数来表达clang和msvc的答案
  • 它应该是可移植的(使用clang或msvc编译x64和AArch64),但我最感兴趣的是使用clang编译时最近的intel和AMD x64架构的性能.
  • 编辑:更新必须是原子的,必须保证全局进度,但正如上面的解决方案,它不一定是一个等待免费的算法(当然,如果你能给我一个,我会很高兴).

c++ x86 arm x86-64 atomic

6
推荐指数
1
解决办法
359
查看次数

应该使用什么 C++ 构造来访问与另一个进程共享的内存

C++ 代码应该如何访问与另一个应用程序共享的内存,例如通过memmapd 文件?选项似乎是:

  1. 常规原始访问,例如int* p = ...address of shared memory...; *p = 5; *p. 这似乎是不安全的,因为允许编译器假设 的内容p是稳定的,但事实并非如此。
  2. 考虑这些操作的一种方法是它们是另一个进程的输入/输出,因此(至少在旧版本的 C++ 中)应该实现的方式似乎是使用volatile.
  3. 由于现代 C++ 包含内置的原子操作,另一种选择是使用原子。在实践中,编译器似乎并没有对这些操作做太多优化,但不清楚是否被标准禁止。

从实验来看,似乎 2 和 3 都在实践中工作(2 没有正确处理弱记忆的复杂性),但是否符合标准?我是否需要使用组合,即访问atomic<volatile int>

c++ language-lawyer c++14 c++17

5
推荐指数
0
解决办法
93
查看次数

为什么只保证std :: atomic_flag无锁?

来自C++ Concurrency in Action:

std :: atomic和std :: atomic_flag之间的区别是std :: atomic可能不是无锁的; 实现可能必须在内部获取互斥锁,以确保操作的原子性

我想知道为什么.如果保证atomic_flag是无锁的,为什么它也不能保证atomic<bool>?这是因为会员功能compare_exchange_weak吗?我知道有些机器缺少单一的比较和交换指令,原因是什么?

multithreading atomic c++11 stdatomic

4
推荐指数
1
解决办法
802
查看次数

在共享内存上使用 volatile 安全吗?

让我们假设如下:

我在 Linux / Mac OS 上有两个进程。

我有mmap共享内存(或在文件中)。

然后在这两个过程中我都有以下内容:

struct Data{
   volatile int reload = 0; // using int because is more standard
   // more things in the future...
};
void *mmap_memory = mmap(...);
Data *data = static_cast<Data *>(mmap_memory); // suppose size is sufficient and all OK
Run Code Online (Sandbox Code Playgroud)

然后在我做的其中一个过程中:

//...
data->reload = 1;
//...
Run Code Online (Sandbox Code Playgroud)

在另一个我做的:

while(...){
    do_some_work();
    //...
    if (data->reload == 1)
        do_reload();
}
Run Code Online (Sandbox Code Playgroud)

这会是线程/进程间安全的吗?

想法来自这里:
https://embeddedartistry.com/blog/2019/03/11/improve-volatile-usage-with-volatile_load-and-volatile_store/

注意:
这对于 来说并不安全std::atomic<>,因为它不“承诺”有关共享内存的任何内容。此外,从两个不同的过程构建/销毁根本不清楚。

c++ volatile shared-memory stdatomic

3
推荐指数
1
解决办法
348
查看次数

C++ 在不同进程之间共享atomic_int64_t?

我正在使用 C++ 多处理,使用共享内存将数据从一个传递到另一个。我将一个数组放入共享内存中。进程A将数据复制到数组中,进程B将使用数组中的数据。然而,进程B需要知道数组中有多少项。

目前我正在使用管道/消息队列将数组大小从A传递到B。但我想我可能会在共享内存中放置一个原子变量(如atomic_uint64_t),在进程A中修改它并在进程B中加载它。但是我有以下问题。

  1. C++中的原子变量在进程之间仍然是原子的吗?我知道原子是通过锁定缓存行来实现的,其他线程或进程都不能修改原子变量。所以我认为答案是肯定的。
  2. 我究竟应该如何在之间共享原子变量?谁能举个例子吗?

c++ atomic multiprocessing

1
推荐指数
1
解决办法
717
查看次数