iOS-原子属性和非原子属性

2020-02-27  本文已影响0人  丁勒个东

在OC中,声明一个属性我们常会用到nonatomic(非原子)或者atomic(原子)来修饰属性.加上这种修饰会影响系统编译时生成的setter/getter方法,如果setter/getter方法为自己重写的,那这种修饰将不起作用.

nonatomic修饰的属性生成的setter/getter方法

//@property(nonatomic, retain) UITextField *userName;
//系统生成的代码如下:

- (UITextField *) userName {
    return _userName;
}

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

atomic修饰的属性生成的setter/getter方法

//@property(retain) UITextField *userName;
//系统生成的代码如下:

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

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

synchronized是自旋锁,如果发现有其它线程正在锁定代码,线程会用死循环的方式,一直等待锁定的代码执行完成。

从上面代码中可以看到, atomic系统自动生成的getter/setter方法会进行加锁操作,而nonatomic系统自动生成的getter/setter方法不会进行加锁操作.

也就是a线程执行get方法过程中,b/c执行set方法时,如果是nonatomic修饰,那么无法确定a得到的值,可能是原始值,也可能是b/c设置的值,甚至抛出异常;如果是atomic修饰,只有等a线程执行完get方法,b/c线程才能依次执行.

atomic并不是绝对的线程安全,它只是对setter/getter方法做了自旋锁,只能让读写安全.譬如在a线程执行set方法时,b线程执行release,就有可能在set时自已已经被释放掉了,因为别的线程还能进行读写之外的其他操作.

总结

atomic(原子属性)保证了getter和setter存取方法的线程安全,但并不能保证整个对象的线程安全.
nonatomic(非原子属性)没有线程安全,但响应迅速耗费资源少,如果没有多线程之间的通讯,使用nonatomic是更好的选择.

上一篇下一篇

猜你喜欢

热点阅读