美文网首页
iOS-原子属性和非原子属性

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

作者: 丁勒个东 | 来源:发表于2020-02-27 22:55 被阅读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是更好的选择.

    相关文章

      网友评论

          本文标题:iOS-原子属性和非原子属性

          本文链接:https://www.haomeiwen.com/subject/nemfhhtx.html