首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >为什么i++在单个核心机器上不安全?

为什么i++在单个核心机器上不安全?
EN

Stack Overflow用户
提问于 2011-05-19 01:16:43
回答 7查看 1.8K关注 0票数 4

可能重复:

Are incrementers / decrementers (var++, var--) etc thread safe?

您能为我描述一下,在汇编代码级别上,为什么从两个不同的线程中增量一个值在单个核心机器上不安全?

EN

回答 7

Stack Overflow用户

回答已采纳

发布于 2011-05-19 01:28:45

考虑可能为像i++这样的语句生成的指令。当然,这将取决于您的体系结构/指令集,但它可能与以下内容类似:

代码语言:javascript
复制
LOAD    @i, r0    ;load the value of 'i' into a register from memory
ADD     r0, 1     ;increment the value in the register
STORE   r0, @i    ;write the updated value back to memory

现在,考虑一下在操作系统中如何实现多线程,而不管机器有多少核心。在最基本的级别上,操作系统需要一些工具来中断当前线程的执行,保存它的状态,并执行上下文切换到另一个线程。操作系统无法自动知道用户线程中的哪些指令应该被视为原子操作,并且能够在任意两个指令之间启动上下文切换。

那么,如果操作系统在LOADADD之间执行上下文从一个线程切换到另一个线程,会发生什么呢?假设i开始时值为0,所以在交换第一个线程时,r0将被设置为0。操作系统将将此值保存为该线程状态的一部分。现在,第二个线程运行,并执行相同的LOAD语句。内存中的值仍然是0,因此r0再次加载到其中。线程增加值并将其写回内存,将i的值设置为1。现在,第一个线程恢复执行,操作系统将r0的值恢复为0,作为上下文切换的一部分。第一个线程现在执行其增量,将r0设置为1,并且1的值再次存储在i中。现在i的值是不正确的,因为已经应用了两个增量,但是这个值只增加了1。

因此,简单地说,即使i++是一种高级语言中的单一语句,它也会生成多个汇编语言指令,除非在它们周围添加额外的同步逻辑,否则这些指令不会被操作系统/运行时环境视为原子指令。

票数 11
EN

Stack Overflow用户

发布于 2011-05-19 01:23:27

i++有三个操作:

将寄存器register

  • Increment

  • 写回i

在这些操作之间,线程可能会被调度程序中断,以便不同的线程能够运行(并修改i)。

票数 9
EN

Stack Overflow用户

发布于 2011-05-19 01:24:04

您的问题是标记汇编程序,但询问有关i++。您无法保证C代码中的i++将编译成一条更改内存的指令。如果您有多个线程使用一条指令从内存中加载i,用另一条指令递增它,然后用第三条指令将它写回内存,那么第一条和第三条之间的线程切换可能会导致i的一些更新丢失。

票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/6052768

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档