在C#中读取和写入某些基本类型,例如bool并且int是原子的.
(参见C#语言规范第5.5节"5.5变量引用的原子性")
但是通过属性访问这些变量呢?假设它们也是原子和线程安全的是否合理?例如,读取MyProperty下面的原子和线程安全?:
public bool MyProperty { get { return _foo; } }
Run Code Online (Sandbox Code Playgroud)
那么自动实现的属性呢?
public bool MyProperty { get; }
Run Code Online (Sandbox Code Playgroud) 我已经读过x86的INC指令不是原子的.我的问题是怎么来的?假设我们在x86-64上递增64位整数,我们可以用一条指令来完成,因为INC指令适用于内存变量和寄存器.那么为什么它不是原子的呢?
AtomicBoolean将其值存储在:
private volatile int value;
Run Code Online (Sandbox Code Playgroud)
然后,例如,提取其值的方式如下:
public final boolean get() {
return value != 0;
}
Run Code Online (Sandbox Code Playgroud)
它背后的原因是什么?为什么没用boolean?
我有一些代码int[]在一个线程中使用int()数组,每秒激活一次.
我使用lock()from std::mutex来锁定这个线程中的数组.
但是我想知道是否有办法创建一个原子数组(或向量)来避免使用互斥锁?我尝试了几种方法,但编译器总是以某种方式抱怨?
我知道有一种方法可以创建一个原子数组,但这是不一样的.
我需要在我的程序中有原子变量.以前我在使用std::atomic<int>,但我现在正在使用的平台没有支持C++ 0x的g ++编译器.我使用volatile int它似乎正在工作,因为我还没有在多核系统中遇到竞争条件我正在测试它.
我的问题是,如果volatile int是原子一样std::atomic<int>?此外,它是否会产生内存障碍(我也需要)?
似乎std::atomic类型不是可复制的可复制的或可复制的.为什么?
是否有技术原因导致无法复制原子类型?或者界面是否有限制以避免某种不良代码?
我想利用C11标准提供的新原子操作.但是,尝试#include使用适当的头文件可以为我提供:
csort-par.c:5:23: fatal error: stdatomic.h: No such file or directory
#include <stdatomic.h>
Run Code Online (Sandbox Code Playgroud)
在文档http://gcc.gnu.org/wiki/C11Status似乎是说,头文件已经提供自GCC 4.7 ...我这么想吗?__STDC_NO_ATOMICS__没有定义.
gcc --version 如下:
gcc (Ubuntu/Linaro 4.8.1-10ubuntu9) 4.8.1
Copyright (C) 2013 Free Software Foundation, Inc.
Run Code Online (Sandbox Code Playgroud)
我确认__STDC_NO_ATOMICS__没有定义如下:
#ifdef __STDC_NO_ATOMICS__
#error yes
#else
#error no
#endif
Run Code Online (Sandbox Code Playgroud)
收益率:
csort-par.c:10:2: error: #error no
#error no
Run Code Online (Sandbox Code Playgroud)
编辑:感谢您的快速回复.
如果有人在谷歌遇到同样的问题而绊倒了这个问题,那么在此期间需要修复,直到他们发布GCC 4.9:
我对以下代码有点困惑:
struct A {
std::atomic<int> a = 0;
};
Run Code Online (Sandbox Code Playgroud)
这给出了一个错误:
复制"std :: atomic"类型的成员子对象调用已删除的构造函数
但几乎相同的代码确实有效:
struct A {
std::atomic<int> a = {0};
};
Run Code Online (Sandbox Code Playgroud)
Okey,如果第一个变体需要复制构造函数,那么它必须使用operator=().可是等等!这个运算符完美地工作,没有复制构造函数:
A a;
a.a = 1;
Run Code Online (Sandbox Code Playgroud)
任何人都可以解释如何在简单操作方面扩展两个就地初始化吗?为什么第一个需要复制构造函数?
它是在cppreference atomic_compare_exchange Talk页面上提出的,现有的实现std::atomic_compare_exchange_weak 用非原子比较指令计算CAS的布尔结果,例如
lock
cmpxchgq %rcx, (%rsp)
cmpq %rdx, %rax
Run Code Online (Sandbox Code Playgroud)
哪个(编辑:为红鲱道歉)
打破CAS循环,例如Concurrency in Action的清单7.2:
while(!head.compare_exchange_weak(new_node->next, new_node);
Run Code Online (Sandbox Code Playgroud)
规范(29.6.5 [atomics.types.operations.req]/21-22)似乎暗示比较的结果必须是原子操作的一部分:
效果:原子比较......
返回:比较的结果
但它实际上是否可以实现?我们应该向供应商或LWG提交错误报告吗?
我的理解std::memory_order_acquire和std::memory_order_release如下:
获取意味着获取围栏之后出现的内存访问不能重新排序到围栏之前.
释放意味着在释放围栏之前出现的内存访问不能在围栏之后重新排序.
我不明白为什么特别是对于C++ 11原子库,获取围栏与加载操作相关联,而释放围栏与存储操作相关联.
为了澄清,C++ 11 <atomic>库允许您以两种方式指定内存屏障:要么可以将fence指定为原子操作的额外参数,例如:
x.load(std::memory_order_acquire);
Run Code Online (Sandbox Code Playgroud)
或者您可以std::memory_order_relaxed单独使用和指定围栅,例如:
x.load(std::memory_order_relaxed);
std::atomic_thread_fence(std::memory_order_acquire);
Run Code Online (Sandbox Code Playgroud)
我不明白的是,鉴于上述获取和发布的定义,为什么C++ 11特别将获取与加载相关联,并与商店一起发布?是的,我已经看过许多示例,这些示例显示了如何使用获取/加载与发布/存储来在线程之间进行同步,但一般来说似乎是获取fences(防止语句后的内存重新排序)和发布的想法fences(在语句之前防止内存重新排序)与加载和存储的想法正交.
那么,为什么,例如,编译器不会让我说:
x.store(10, std::memory_order_acquire);
Run Code Online (Sandbox Code Playgroud)
我意识到我可以通过使用memory_order_relaxed,然后单独的atomic_thread_fence(memory_order_acquire)声明来完成上述操作,但同样,为什么我不能直接使用存储memory_order_acquire?
一个可能的用例可能是,如果我想确保某些存储,比如在执行可能影响其他线程的其他语句之前x = 10发生.