预先自动引用计数,你可以在Objective-c中进行适当的指针转换,以允许你使用bool OSAtomicCompareAndSwapPtr(void * oldValue,void * newValue,void * volatile * theValue);在处理多线程访问时尝试以原子方式交换指针。
在ARC下,这些指针强制转换无效。在ARC for iOS下是否有可用的等效原子指针交换?如果这个替代方案仍然可用,我希望避免更昂贵的锁定。
答案 0 :(得分:0)
如果满足一个条件,您可以轻松地使用它,也许如果您愿意玩游戏。
创建一个新文件,在Build Phase中将其标记为不使用ARC,并将此交换放入一个小C函数中。在函数的顶部获取对象的retainCounts,如果它们相等(并且你有理由相信它们不在自动释放池中),你可以交换它们,因为ARC将确保每个都有适当的版本。
如果他们不平等,那么你可以通过更改保留计数来玩游戏。
答案 1 :(得分:0)
免责声明:此答案中的代码未经过测试!
首先,我想提一下大多数指针使用并不需要比较和交换。 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;
}