代码之家  ›  专栏  ›  技术社区  ›  Tenfour04

原子对于合成的原始体来说真的有意义吗?

  •  6
  • Tenfour04  · 技术社区  · 11 年前

    在Android中,我可以从不同的线程安全地访问和修改原始类型。我用它在OpenGL绘制循环和在主线程Android UI中修改的用户设置之间共享数据。通过将每个设置存储在基元类型中,并使每个设置独立于其他设置的值,可以在不使用锁或synchronize关键字的情况下修改所有这些变量,这是线程安全的。

    在Objective-C中也是这样吗?我读到,在变量上放置原子本质上会导致合成的getter和setter使用锁,类似于在Java中使用同步方法。我已经读到,这样做的原因是,当另一个线程读取对象时,它不会被部分修改。

    但是,基元类型是否可以像Java中那样安全地避免被部分修改?如果是这样的话,我似乎可以使用Java中的旧范式在线程之间共享数据。但是,atomic关键字对于一个原语来说是毫无意义的,对吗?

    我还读到,一个比使用原子变量更健壮、更快的解决方案是,如果从多个线程访问对象,则在使用对象之前先复制对象。但我不确定如何才能做到这一点。一个非原子对象在被复制的过程中不能被修改,从而破坏副本吗?

    3 回复  |  直到 11 年前
        1
  •  6
  •   Tommy    11 年前

    基元类型不能保证不会被部分修改,因为对基元类型的修改不能保证在C中是原子的,Objective-C从那里继承。C只保证关注序列点,不要求两个序列点之间的处理是原子的——经验法则是每个完整的表达式都是一个序列点。

    在实践中,修改基元通常是一个分两步的过程;在寄存器中进行修改,然后将其写入存储器。写入本身不太可能是原子的,但也不能保证它何时会发生,而不是修改。即使有 volatile 资格,所提供的唯一保证是在序列点方面。

    苹果通过 OSAtomic.h 直接映射到CPU为实现并发机制提供的专门原子指令。你可以更直接地使用其中一个,而不是通过一个强大的互斥体。

    Objective-C中的常见模式有:

    • 不可变对象和函数转换也有内存管理的原因,但这也是部分原因 NSString , NSArray 等,与 NSMutableString , NSMutableArray
    • 串行调度队列,可以与复制-修改-替换相结合,方法是在队列上复制,到其他地方进行修改,然后跳回队列进行替换;
    • 这样的 @synchronized s NSConditionLock s或其他适当的显式同步机制。

    主线程本身是一个串行调度队列,这就是为什么如果您将自己限制在并发性问题上,则可以完全忽略并发性问题。

        2
  •  3
  •   Greg Parker    11 年前

    原子合成@财产不受并发部分更新的影响。如果需要,访问器方法将在该体系结构上使用锁。

    一般来说,对于并发的部分更新,C中的基元类型不一定是安全的。

        3
  •  -2
  •   Community kfsone    7 年前

    我不相信你可以部分修改一个原始类型,这是它们原始的部分原因。你要么修改它,要么不修改。从这个意义上说,我想说它们是线程安全的。

    当你说atomic关键字对于基元类型来说毫无意义时,你是正确的。

    有人已经在这里捅了一刀: Objective-c properties for primitive types