考虑以下情况:
F
。A
重复为F
分配一个随机值(不考虑先前的F
值)。B
与线程A
完全相同(独立于A
)。C
重复读取F
的值(并打印出来)。这是在x64架构上的Windows上的C ++(Visual C ++),多处理器。 F
的类型为bool
并标记为volatile
,并且所有访问均不受任何锁保护。
问题:这种情况有什么线程不安全的吗?
假设代码的逻辑行为有效,那么多个线程是否同时读取和写入值到同一位置的事实是否有任何不安全感?
可以保证(跨架构,操作系统,编译器)保证读取和写入平台上< = word-size的变量的原子性? (我假设单词大小很重要......)
在相关的说明中,什么是线程之间通信的可接受方式,某些操作的完成状态(没有线程等待操作完成,他们可能只是有兴趣不时查询状态)?
答案 0 :(得分:2)
这取决于您的线程安全要求。你总是得到一致的值(也就是说,你不可能得到线程A的写入值的一半而另一半来自线程B),但无保证表示你的值事实上,阅读是最新的逻辑写作。
这里的问题是可能会或可能不会刷新的CPU缓存。当线程写入内存时,该值首先进入缓存,最终将其写入内存。与此同时,如果其他核心试图从内存中读取对象,它们将获得旧值。
答案 1 :(得分:2)
在x86下,对正确对齐其大小的类型的任何读取或写入都被认为是原子的(因此对于bool
它只需要1字节对齐boundery),但建议使用explict atomic他们提供便携性和内存障碍。摘自英特尔系统编程指南,第3A卷,第8节2011年5月(还有另一个,无法找到它)。
Intel486处理器(以及更新的处理器)保证以下内容 基本的内存操作将始终以原子方式执行:
•读取或写入字节
•读取或写入在16位边界上对齐的字
•读取或写入在32位边界上对齐的双字
Pentium处理器(以及更新的处理器)保证以下内容 额外的内存操作将始终以原子方式执行:
•读取或写入在64位边界上对齐的四字
•16位访问适合32位数据总线的未缓存内存位置
P6系列处理器(以及更新的处理器)保证以下内容 额外的内存操作将始终以原子方式执行:
•对缓存中的高速缓存内存进行未对齐的16位,32位和64位访问 线
微软也有a few examples使用volatitle bool
来发送信号线程出口,但是,如果你想发信号通知正在等待的线程,最好使用内核结构,在windows上这将是一个event(请参阅CreateEventA/W
),这样可以防止在尚未设置变量的情况下等待cpu循环等待。
对于几乎没有等待时间的线程,最好实现用户级别的锁定,如果它具有高争用环境,则可选择退避,intel在here上有一篇好文章,或者你可以使用WinAPI的CriticalSections(这些是半内核级别)。