聲明:此答案中的驗證碼未經測試!
首先我想提一下,大多數指針的使用並不需要比較和交換。 C指針的讀寫操作本身就是原子的。有關更多詳細信息,請參閱this SO answer。 ARM也一樣。所以,如果你實現原子getter和setter你只需要一個內存屏障,以保證其他線程看到完全初始化的對象:
NSObject * global;
NSObject * get() { return global; }
void set(NSObject * value) { OSMemoryBarrier(); global = value; }
現在回到正題,因爲誰知道,也許有用於比較和實際用途 - 吸引物體。石膏仍然是可能的,你只需要聲明他們現在不同:
NSString * a = @"A";
NSObject * b = @"B";
OSAtomicCompareAndSwapPtrBarrier(
(__bridge void *)a,
(__bridge void *)b,
(__bridge void * *)&a);
然而這段代碼有問題:字符串@"A"
失去參考,並@"B"
被引用了兩次,不知道ARC。因此@"A"
將會泄漏,並且程序在離開示波器時可能會崩潰,因爲@"B"
將被釋放兩次,而只有保留計數器爲1
。
我認爲唯一的選擇是使用Core Foundation對象。你可以使用NSObject免費橋接CFType的事實。我找不到任何關於這方面的明確文件,但是它來自常識和實際證據。所以例如有可能實現一個單身人士:
CFTypeRef instance;
Thingamabob * getInstance() {
if (!instance) {
CFTypeRef t = (__bridge_retained CFTypeRef)[Thingamabob new];
if (!OSAtomicCompareAndSwapPtrBarrier(NULL, t, &instance)) {
CFRelease(t);
}
}
return (__bridge Thingamabob *)instance;
}
謝謝。不幸的是,這使得依賴於檢查保留計數向交換添加了另一個非線程安全的步驟。考慮到交換的性能優勢,我希望它在遷移到ARC時不會被遺忘。好吧,我會做更多的強化鎖定。 – FooBard