2012-01-09 56 views
3

的问题是相当简单的问: 如果我有是否性病::原子防止非原子变量的重新排序在原子变量

settings[N_STNGS];//used by many threads 
std::atomic<size_t> current_settings(0); 
void updateSettings()//called by single thread , always the same thread if that is important 
{ 

    auto new_settings = (current_settings+1)%N_STNGS; 
    settings[new_settings].loadFromFileSystem(); //line A 
    current_settings=new_settings; //line B 
} 

做标准保证线B线后不会重新排序? STNGS的用户也总是会看到一致的(提交 - 在内存中的可见性可见)数据?

编辑:对于多个读者线程和非平凡的设置,这是值得比较简单的互斥麻烦?

+1

即使不是这样,这段代码也完全破坏了。 ('current_settings'可以通过第一行和最后一行之间的其他线程改变。) – ybungalobill 2012-01-09 17:21:14

+0

@DavidSchwartz:考虑char padding [padding_size];在struct的开头和结尾。另外STNGS可以是指针数组,不会改变,只是指向东西... – NoSenseEtAl 2012-01-09 17:23:23

+0

@NoSenseEtAl这是一个C++的问题或关于某个特定平台的问题?如果这是一个C++问题,那么就不能保证填充是你所需要的。如果这是一个特定于平台的问题,答案将取决于平台。 (你对'settings'的修改是永远不会改变的。) – 2012-01-09 17:24:45

回答

0

一般的答案是否定的。如果你很小心,并且只使用具有memory_order参数的函数,并根据你正在做的事情给它们传递正确的值,那么它可能是肯定的。

(和其他人指出,你的代码有问题。例如,按值返回一个原子<>类型没有意义对我来说)。

2

给出的定义

int settings[N_STNGS]; 
std::atomic<size_t> current_settings(0); 

和线程1执行:

settings[new_settings] = somevalue; // line A 
current_settings=new_settings;  // line B 

和线程2执行:

int cur_settings = current_settings;  // line X 
int setting_value = settings[cur_settings]; // line Y 

然后是,如果线程2的行X读取new_settings在B行写线程1,并且没有其他修改settings[new_settings](由一些代码,我们看不到),线程2势必阅读somevalue和没有未定义的行为发生。这是因为所有操作都是(默认情况下)memory_order_seq_cst,并且释放写入(行B)与获取读取(行X)同步。请注意,线程2中需要两条语句才能获得索引的原子读取和值的读取之间的先后顺序关系(取而代之,操作将执行memory_order_consume)。

我肯定会用rw-mutexes来启动它。

+0

我同意。第X行可以读取初始值0或B写入的值之一,在这种情况下,B和X之间存在发生前的关系。A在B之前由程序顺序发生,X在Y之前发生。由于发生 - 关系之前的关系是可传递的,A发生在Y之前。没有关系,A和Y中的代码不是原子的。唯一的担心是使用循环缓冲区。从理论上讲'current_settings'可能包含在X和Y行之间。这将导致A和Y之间的数据竞争。 – 2012-01-10 05:53:13

+0

@BartoszMilewski非常不可能,因为更新设置每隔几秒完成一次,所以这将是一些隐藏内存可见性模型(我的意思是这将是最糟糕的高速缓存一致性CPU模型),在这种情况下会出现问题。 – NoSenseEtAl 2012-01-10 08:25:42

+0

可以肯定的是:您是在评论设置*内容*,还是仅仅是圆形阵列设置的索引。 – NoSenseEtAl 2012-01-10 08:34:41