ios - 在迭代之前复制集合是否足以防止同步问题?

标签 ios objective-c multithreading synchronization

我有一个 sessions 属性,一个可变集。我需要迭代集合,但同时我可以用另一种方法更改集合:

- (Session*) sessionWithID: (NSString*) sessionID
{
    for (Session *candidate in _sessions) {
        /* do something */
    }
    return nil;
}

- (void) doSomethingElse
{
    [_sessions removeObject:…];
}

这不是线程安全的。防弹版本将使用 @synchronized 或调度队列来序列化 _sessions 访问。但是在迭代集合之前简单地复制它有多合理?

- (Session*) sessionWithID: (NSString*) sessionID
{
    for (Session *candidate in [_sessions copy]) {
        /* do something */
    }
    return nil;
}

我不太关心性能差异。

最佳答案

But how reasonable is to simply copy the set before iterating over it?

如前所述,不保证线程安全。您需要保证 _sessions-copy 期间不会发生变化。然后迭代不可变的副本是安全的,_sessions 的突变可能会发生在辅助线程或您的实现中。

在许多 Cocoa 集合的情况下,您会发现最好使用不可变的 ivars 和通过将属性声明为 NSSet 类型的 copy在集合上复制 。这样,您可以在写入/设置时进行复制,然后避免在读取时进行复制。这有可能减少副本,具体取决于程序的实际执行方式。一般来说,仅此还不够,您将需要更高级别的同步。

还请记住,集合中的Session可能不是线程安全的。即使您的集合访问受到适当保护,您也可能需要保护对这些对象的访问。

关于ios - 在迭代之前复制集合是否足以防止同步问题?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/21857612/

相关文章:

ios - 有没有办法让子类不响应其父类(super class)实现的方法,并让编译器抛出错误?

iphone - 应用程序在 super dealloc 方法中崩溃

objective-c - 将自定义 View 拖到 Interface Builder 中的窗口上?

objective-c - 如何手动创建 UISplitView?

multithreading - 如何修复 Java 绑定(bind) : UnsatisfiedLinkError?

mysql - MySQL复制实际上如何工作? (关于线程)

iphone - iOS 设备休眠时 Mach Time 停止计数

ios - 实现这个的好方法?

java - ZeroMQ 多线程 : create sockets on-demand or use sockets object pool?

ios - 如何检测iOS屏幕是OLED?