原子和非原子属性之间有什么区别?

属性声明中的atomicnonatomic是什么意思?

@property(nonatomic, retain) UITextField *userName;
@property(atomic, retain) UITextField *userName;
@property(retain) UITextField *userName;

这三者之间的运作差异是什么?


最后两个是相同的; “atomic”是默认行为(请注意,它实际上并不是一个关键字;它仅由缺少nonatomic atomic来指定 - atomic在最新版本的llvm / clang中被添加为关键字)。

假设您在@方法实现方法实现,原子与非原子更改生成的代码。 如果你正在编写你自己的setter / getters,atomic / nonatomic / retain / assign / copy只是顾问。 (注意:@synthesize现在是LLVM最新版本中的默认行为,也不需要声明实例变量;它们也会自动合成,并且会在名称前加上_ ,以防止意外的直接访问)。

对于“原子”,合成的setter / getter将确保始终从getter返回整个值或由setter设置,而不管任何其他线程上的setter活动。 也就是说,如果线程A位于getter的中间,而线程B调用setter,则实际可用的值 - 最有可能的自动释放对象 - 将在A中返回给调用者。

nonatomic ,没有这样的保证。 因此, nonatomic比“原子”快得多。

什么“原子” 就是做出关于线程安全的任何保证。 如果线程A在线程B和C同时调用getter时使用不同的值调用setter,则线程A可能会返回三个返回值中的任何一个值 - 在调用任何setter之前的值或者传入setters的任一值在B和C中。同样,对象可能以B或C的值结束,无法说明。

确保数据完整性 - 多线程编程的主要挑战之一 - 是通过其他方式实现的。

除此之外:

单个属性的atomicity性也不能保证多个相关属性在玩时的线程安全性。

考虑:

 @property(atomic, copy) NSString *firstName;
 @property(atomic, copy) NSString *lastName;
 @property(readonly, atomic, copy) NSString *fullName;

在这种情况下,线程A可以通过调用setFirstName:来重命名对象,然后调用setLastName: 同时,线程B可能会在线程A的两个调用之间调用fullName ,并且会接收到与旧姓氏结合的新名字。

为了解决这个问题,你需要一个事务模型。 即一些其他类型的同步和/或排除,允许在更新从属属性时排除对fullName访问。


这在Apple的文档中有解释,但下面是实际发生的一些示例。 请注意,没有“原子”关键字,如果不指定“非原子”,那么属性是原子的,但明确指定“原子”会导致错误。

//@property(nonatomic, retain) UITextField *userName;
//Generates roughly

- (UITextField *) userName {
    return userName;
}

- (void) setUserName:(UITextField *)userName_ {
    [userName_ retain];
    [userName release];
    userName = userName_;
}

现在,原子变体有点复杂:

//@property(retain) UITextField *userName;
//Generates roughly

- (UITextField *) userName {
    UITextField *retval = nil;
    @synchronized(self) {
        retval = [[userName retain] autorelease];
    }
    return retval;
}

- (void) setUserName:(UITextField *)userName_ {
    @synchronized(self) {
      [userName_ retain];
      [userName release];
      userName = userName_;
    }
}

基本上,为了确保线程安全,原子版本必须锁定,并且还要触发对象的引用计数(以及autorelease计数以平衡它),以便确保对象存在于对象中,否则将存在如果另一个线程正在设置该值,则会导致竞争条件下降到0。

事实上,这些东西有很多不同的变体,取决于属性是标量值还是对象,以及保留,复制,只读,非原子等等如何相互作用。 一般来说,地产合成器只知道如何为所有组合“做正确的事情”。


原子

  • 是默认行为
  • 将在另一个进程访问该变量之前确保当前进程由CPU完成
  • 并不快,因为它可以确保整个过程完成
  • 非原子

  • 不是默认行为
  • 更快(对于合成代码,也就是使用@property和@synthesize创建的变量)
  • 不是线程安全的
  • 可能会导致意外的行为,当两个不同的进程同时访问相同的变量时
  • 链接地址: http://www.djcxy.com/p/20691.html

    上一篇: What's the difference between the atomic and nonatomic attributes?

    下一篇: What's the best way to communicate between view controllers?