【问题标题】:Alternatives to pervasive use of the @synchronized directive on mutable array access在可变数组访问中普遍使用 @synchronized 指令的替代方法
【发布时间】:2017-02-23 06:49:26
【问题描述】:

我正在 Objective-C 中设计一个单例类,它将被多个线程访问。我的班级有 3-4 个NSMutableArrays,外部班级可以通过 read、add 和 remove 操作进行访问,这些操作当然包含在这个班级中。

由于NSMutableArray 不是线程安全的,我使用@synchronized() 使我的操作线程安全,但是它会导致@synchronized() 块的使用过多。

因为对于每个 3-4 个数组,我至少有 1 个添加函数、1 个删除函数和 5 次我需要读取值。因此,对于 1 个数组,我至少使用 7 个 @synchronized() 块。 对于 4 个数组,我需要在我的单例类中添加 28 个 @synchronized

有没有更好的方法来解决我的问题? 或者,如果我确实使用了所有这些@synchronized 指令,会导致问题吗?

我知道如果我想让我的对象线程安全,它会减慢我的代码,但除此之外还有什么缺点吗?

【问题讨论】:

  • 1) 如果你的单例是线程安全的,那么你可能不需要担心它的数据成员,在你的情况下是 NSMutableArray。 2) 您一定听说过并使用过数据成员的atomic/nonatomic 属性。前者使它们线程安全。为了额外的安全性,你可以声明你的 NSMutableArrays 是原子的。
  • 另一种方法是为每个数组创建一个串行调度队列。然后,您可以在数组更新方法中将数组更新同步分派到相关队列中。 @Adeel,使 NSMutable 数组属性原子化不会使底层数组线程安全,只会使属性本身。
  • @Adeel:对可变对象类型的属性使用 atomic 属性绝对没有来同步突变。它不会使它成为“线程安全的”。它只做一件事和一件事:它确保 getter 和 setter 不会被中断。之后对象会发生什么不受控制。
  • @Adeel ,如何制作一个完美的线程安全单例类?我刚刚用调度一次守卫进行了初始化。并尝试在我访问 MutableArrays 的关键部分添加同步。而且我也不认为使用原子属性使我的数组线程安全。

标签: ios objective-c multithreading thread-safety synchronized


【解决方案1】:

通常仅仅同步原始调用 (CRUD) 以获得线程安全是不够的。这个细粒度级别只是基本的,但您还必须在更全局的级别上进行思考并“原子化”大量代码。如何做到这一点在很大程度上取决于您的实际实施。多线程是邪恶的(tm)并且需要全面的视图,因此对此没有一般的答案。

同步块通常会减慢您的应用程序的速度,至少在调用过于频繁的情况下是这样。有时最好将多个调用组合在一个同步块中,以避免锁定开销。或者,如果调用非常短,您可以使用自旋锁来防止不必要的任务暂停(请参阅here for an old question/answer)。

更多详情您可以咨询Apple documentation

【讨论】:

  • 我是objective c的新手,我在linux工作过,自旋锁和objective c mutex是否类似于pthread_mutex_lock?使用 synchronized 和 pthread_mutex_lock 需要权衡取舍,因为 synchronized 不会将代码锁定在同一线程或函数堆栈中,而 pthread_mutex_lock 可以锁定在同一线程和函数调用堆栈中。 同步还有一个好处,你可以在任何时候使用return,它会自动解锁。但是使用 pthread_mutex_lock 如果你错过任何一个条件,它会让你的生活变得地狱。
  • 我认为细节已经在这里分析了:stackoverflow.com/questions/9463525/… - 自旋锁完全不同,因为它的原因是“活跃”等待,并且仅在非常短的调用时才被推荐。
  • 感谢您的回答。很抱歉,我忘了提到自旋锁将是一个坏主意的 iOS。正如您所建议的,我认为对于我的场景,递归互斥锁会更合适。
猜你喜欢
  • 1970-01-01
  • 2018-04-16
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-12-15
  • 1970-01-01
  • 2014-12-24
  • 1970-01-01
相关资源
最近更新 更多