我假設在像iPhone這樣的32位設備上,分配一個短浮點是一個原子線程安全的操作。我想確保它是。我有我想從一個Objective-C線程調用C函數,而我不希望調用它之前獲得鎖:是單浮動分配在iPhone上的原子操作?
void setFloatValue(float value) {
globalFloat = value;
}
我假設在像iPhone這樣的32位設備上,分配一個短浮點是一個原子線程安全的操作。我想確保它是。我有我想從一個Objective-C線程調用C函數,而我不希望調用它之前獲得鎖:是單浮動分配在iPhone上的原子操作?
void setFloatValue(float value) {
globalFloat = value;
}
在32位ARM,上面的函數會被編譯到
ldr r2, [pc, #0x??] ; to retrieve the address of globalFloat
str r0, [r2] ; store value into globalFloat
由於有2個指令,並且CPU可以自由地在它們之間進行任何東西,但只有第二指令str r0, [r2]
影響記憶。除非globalFloat
未對齊,CPU可以對其執行單拷貝原子寫入。
當全局指針未對齊時,賦值可以是非原子的。如果你正在寫一個更大的結構,例如它也是非原子的。的CGRect。
對於線程安全來說,原子是不夠的。由於緩存和指令重新排序,您的更改可能對其他CPU內核不可見。您可能需要插入OSMemoryBarrier()
以「發佈」更改。
當涉及複合操作時(例如globalFloat += value
),原子操作通常很有趣。你可能想看看它的內置OSAtomic
庫。
是的,它會是原子的。在32位體系結構上,對32位或更小(char,short,int,long,float等)基本數據類型的任何存儲操作都將是原子操作。
還有更多的問題不只是原子性。即使寫入是原子性的,也不能保證另一個線程不會在沒有某種內存障礙的情況下看到更改。這對目前的iPhone來說可能不是問題,因爲它們只有一個CPU,但在臺式機上可能會出現問題。
參見:
但這仍然是 「有點兒八九不離十原子」,在全球國家的實際寫入是一個單一的指令,所以沒有人看到globalFloat可以在中間狀態下看到它。 – unwind 2010-03-31 07:02:39
沒有一個用於分配。 – 2010-03-31 07:02:48
@unwind:任何商店指令都是如此。這裏的中間狀態是在它被讀取之後並且在它被寫入之前,當變量物理地存在於兩個地方(存儲器和寄存器)時。 – Potatoswatter 2010-03-31 07:06:57