可能重复:
Are incrementers / decrementers (var++, var--) etc thread safe?
您能为我描述一下,在汇编代码级别上,为什么从两个不同的线程中增量一个值在单个核心机器上不安全?
发布于 2011-05-19 01:28:45
考虑可能为像i++这样的语句生成的指令。当然,这将取决于您的体系结构/指令集,但它可能与以下内容类似:
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现在,考虑一下在操作系统中如何实现多线程,而不管机器有多少核心。在最基本的级别上,操作系统需要一些工具来中断当前线程的执行,保存它的状态,并执行上下文切换到另一个线程。操作系统无法自动知道用户线程中的哪些指令应该被视为原子操作,并且能够在任意两个指令之间启动上下文切换。
那么,如果操作系统在LOAD和ADD之间执行上下文从一个线程切换到另一个线程,会发生什么呢?假设i开始时值为0,所以在交换第一个线程时,r0将被设置为0。操作系统将将此值保存为该线程状态的一部分。现在,第二个线程运行,并执行相同的LOAD语句。内存中的值仍然是0,因此r0再次加载到其中。线程增加值并将其写回内存,将i的值设置为1。现在,第一个线程恢复执行,操作系统将r0的值恢复为0,作为上下文切换的一部分。第一个线程现在执行其增量,将r0设置为1,并且1的值再次存储在i中。现在i的值是不正确的,因为已经应用了两个增量,但是这个值只增加了1。
因此,简单地说,即使i++是一种高级语言中的单一语句,它也会生成多个汇编语言指令,除非在它们周围添加额外的同步逻辑,否则这些指令不会被操作系统/运行时环境视为原子指令。
发布于 2011-05-19 01:23:27
i++有三个操作:
将寄存器register
i在这些操作之间,线程可能会被调度程序中断,以便不同的线程能够运行(并修改i)。
发布于 2011-05-19 01:24:04
您的问题是标记汇编程序,但询问有关i++。您无法保证C代码中的i++将编译成一条更改内存的指令。如果您有多个线程使用一条指令从内存中加载i,用另一条指令递增它,然后用第三条指令将它写回内存,那么第一条和第三条之间的线程切换可能会导致i的一些更新丢失。
https://stackoverflow.com/questions/6052768
复制相似问题