1

预自动引用计数,您可以在 Objective-c 中进行适当的指针转换,以允许您使用 bool OSAtomicCompareAndSwapPtr(void* oldValue, void* newValue, void* volatile *theValue); 在处理多线程访问时尝试原子交换指针。

在 ARC 下,这些指针转换无效。ARC for iOS 下是否有等效的原子指针交换?如果这种替代方案仍然可用,我希望避免更昂贵的锁定。

4

2 回答 2

0

如果满足一个条件,或者如果您愿意玩游戏,您也许可以轻松使用它。

创建一个新文件,在构建阶段将其标记为不使用 ARC,并将此交换放入一个小的 C 函数中。在函数的顶部获取对象的 retainCounts,如果它们相等(并且您有理由相信它们不在自动释放池中),您可以交换它们,因为 ARC 将确保对每个对象进行正确的释放。

如果它们不相等,那么您可以通过更改保留计数来玩游戏。

于 2012-09-12T12:06:48.547 回答
0

免责声明:此答案中的代码未经测试!

首先我想提一下,大多数指针的使用并不真正需要比较和交换。C 指针读取和写入本身是原子的。有关更多详细信息,请参阅此 SO 答案。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;
}
于 2014-07-23T20:29:45.340 回答