是C/C++的基本类型,如int,double等,原子,如线程?
他们是否免于数据竞赛; 也就是说,如果一个线程写入这种类型的对象而另一个线程从中读取,那么行为是否定义明确?
如果没有,它是否依赖于编译器或其他东西?
每个现代操作系统都提供一些原子操作:
Interlocked*API<machine/atomic.h><atomic.h><libkern/OSAtomic.h>对Linux有什么相似之处?
问题:
__sync_*并非所有平台(ARM)都支持GCC原子内置,并且英特尔编译器不支持.<asm/atomic.h>不应该在用户空间中使用,我根本没有成功使用它.此外,我不确定它是否适用于英特尔编译器.有什么建议?
我知道有很多相关的问题,但有些问题指出__sync*哪些对我来说是不可行的(ARM),有些人指出asm/atomic.h.
也许有一个内联汇编库可以为GCC执行此操作(ICC支持gcc汇编)?
编辑:
仅对添加操作有一个非常局部的解决方案(允许实现原子计数器但不能锁定需要CAS的自由结构):
如果您使用libstc++(英特尔编译器使用libstdc++),那么您可以使用或__gnu_cxx::__exchange_and_add中定义的.取决于编译器版本.<ext/atomicity.h><bits/atomicity.h>
但是,我仍然希望看到支持CAS的东西.
我想知道atomically:该writeToFile:atomically:方法中的参数代表什么(-[NSArray writeToFile:atomically:]例如).这是常见YES的atomically:,但我不知道这意味着什么.
我已经查看了SO中的其他volatile和Atomicxxxx问题(包括这个),并阅读了java.util.current.atomic的描述,我对细微差别不太满意.
如果我在尝试使用volatile boolean和之间做出决定AtomicBoolean,除了AtomicBoolean提供的原子读取 - 修改 - 写入操作之外是否存在实际差异?(例如compareAndSet()和getAndSet())
假设我有
volatile boolean flag;
Run Code Online (Sandbox Code Playgroud)
然后一个或多个线程设置标志(但不清除它).如果我有一个线程读取标志,如果设置,执行操作,然后清除标志,是否volatile足够?
AtomicBoolean的成本是否高于volatile布尔值
volatile boolean似乎需要内存防护,AtomicBoolean似乎需要内存防护+根据java.util.current.atomic描述对CAS操作进行一些小锁定)我的直觉调用是使用AtomicBoolean并且是安全的,但我想了解是否有任何情况可以使用volatile boolean(例如,如果我有数千个实例,性能是一个问题).
对于像计数器那样简单的东西,如果多个线程将增加数量.我读到互斥锁会降低效率,因为线程必须等待.所以,对我来说,一个原子计数器将是最有效的,但我在内部读到它基本上是一个锁?所以我想我很困惑如何比另一个更有效率.
我使用Python在一个操作中将文本块写入文件:
open(file, 'w').write(text)
Run Code Online (Sandbox Code Playgroud)
如果脚本被中断,那么文件写入没有完成我想要没有文件而不是部分完整的文件.可以这样做吗?
是否有系统的方法来了解C#中的操作是否是原子操作?或者是否有任何一般指导方针或经验法则?
在SQL Server 2005中执行原子"UPSERT"(在哪里存在UPDATE,否则为INSERT)的正确模式是什么?
我在SO上看到了很多代码(例如,请参阅检查是否存在行,否则插入),其中包含以下两部分模式:
UPDATE ...
FROM ...
WHERE <condition>
-- race condition risk here
IF @@ROWCOUNT = 0
INSERT ...
Run Code Online (Sandbox Code Playgroud)
要么
IF (SELECT COUNT(*) FROM ... WHERE <condition>) = 0
-- race condition risk here
INSERT ...
ELSE
UPDATE ...
Run Code Online (Sandbox Code Playgroud)
其中<condition>将是对自然键的评估.上述方法似乎都不能很好地处理并发问题.如果我不能拥有两个具有相同自然键的行,则似乎所有上述风险都会在竞争条件场景中插入具有相同自然键的行.
我一直在使用以下方法,但我很惊讶不要在人们的回复中看到它,所以我想知道它有什么问题:
INSERT INTO <table>
SELECT <natural keys>, <other stuff...>
FROM <table>
WHERE NOT EXISTS
-- race condition risk here?
( SELECT 1 FROM <table> WHERE <natural keys> )
UPDATE ...
WHERE <natural keys>
Run Code Online (Sandbox Code Playgroud)
请注意,此处提到的竞争条件与早期代码中的竞争条件不同.在早期的代码中,问题是幻读(在UPDATE/IF之间或在另一个会话的SELECT/INSERT之间插入行).在上面的代码中,竞争条件与DELETE有关.在(WHERE NOT EXISTS)执行之后但在INSERT执行之前,是否有可能由另一个会话删除匹配的行?目前还不清楚WHERE …
java内存模型强制要求写一个int是原子的:也就是说,如果你在一个线程中写一个值(由4个字节组成)并在另一个线程中读取它,你将获得所有字节或没有,但永远不会有2个新字节和2个旧字节或类似的.
这不保证long.在这里,写入之前0x1122334455667788保存的变量0可能导致另一个线程读取0x112233440000000或0x0000000055667788.
现在,规范并未强制对象引用为int或long.出于类型安全的原因,我怀疑它们是保证以原子方式编写的,但在64位VM上,这些引用可能是非常好的64位值(仅仅是内存地址).
现在我的问题是:
此致,斯蒂芬
我读了一章,我不喜欢它.我还不清楚每个内存顺序之间的差异.这是我目前的推测,我在阅读更简单的http://en.cppreference.com/w/cpp/atomic/memory_order后理解这一点.
以下是错误的,所以不要试图从中学习
a在另一个线程上放宽了存储.我b用seq_cst 存储.第三个线程读取a 放松将看到变化以及b任何其他原子变量? ).如果我错了,我想我理解但是纠正我.我找不到任何用易于阅读的英语解释它的东西.
atomic ×10
c++ ×3
c ×2
java ×2
memory-model ×2
.net ×1
c# ×1
c++11 ×1
cocoa-touch ×1
concurrency ×1
file-io ×1
ios ×1
linux ×1
mutex ×1
objective-c ×1
pthreads ×1
python ×1
reference ×1
sql-server ×1
upsert ×1
volatile ×1
writetofile ×1