zoukankan      html  css  js  c++  java
  • @property修饰符种类

    @property修饰符种类
     
    当我们定义一个字符串属性时,通常我们会这样写:
    @property (nonatomic, copy) NSString *name;
    复制代码
    当我们定义一个NSMutableArray类型的属性时,通常我们会这样写:
    @property (nonatomic, strong) NSMutableArray *books;
    复制代码
    而当我们定一个基本数据类型时,会这样写:
    @property (nonatomic, assign) int age;
    复制代码
    定义一个属性时,nonatomic、copy、strong、assign等被称作是关键字,或者是修饰符。

    修饰符种类

    修饰符有四种:
    1. 原子性。原子性有nonatomic、atomic两个值,如果不写nonatomic,那么默认是atomic的。如果属性是atomic的,那么在访问其getter和setter方法之前,会有一些判断,大概是判断是否可以访问等,这里系统使用的是自旋锁。由于使用atomic并不能绝对保证线程安全,且会耗费一些性能,因此通常情况下都使用nonatomic。
    2. 读写权限。读写权限有两个取值,readwrite和readonly。声明属性时,如果不指定读写权限,那么默认是readwrite的。如果某个属性不想让其他人来写,那么可以设置成readonly。
    3. 内存管理。内存管理的取值有assign、strong、weak、copy、unsafe_unretained。
    4. set、get方法名。如果不想使用自动合成所生成的setter、getter方法,声明属性时甚至可以指定方法名。比如指定getter方法名:
    @property (nonatomic, assign, getter=isPass) BOOL pass;
    复制代码
    属性pass的getter方法就是
    - (BOOL)isPass;
    复制代码

    默认修饰符

    声明属性时,如果不显示指定修饰符,那么默认的修饰符是哪些呢?或者说未指定的修饰符,默认取值是什么呢?
    如果是基本数据类型,默认取值是:atomic,readwrite,assign
     
    如果是Objective-C对象,默认取值是:atomic,readwrite,strong
     

    atomic是否是线程安全的

    上面提到了,声明属性时,通常使用nonatomic修饰符,原因就是因为atomic并不能保证绝对的线程安全。举例来说:
    单独的原子操作绝对是线程安全的,但是组合一起的操作就不能保证。
     1 - (void)competition {
     2 self.intSource = 0;
     3  
     4 dispatch_async(queue1, ^{
     5 for (int i = 0; i < 10000; i++) {
     6 self.intSource = self.intSource + 1;
     7 }
     8 });
     9  
    10 dispatch_async(queue2, ^{
    11 for (int i = 0; i < 10000; i++) {
    12 self.intSource = self.intSource + 1;
    13 }
    14 });
    15 }
    最终得到的结果肯定小于20000。当获取值的时候都是原子线程安全操作,比如两个线程依序获取了当前值 0,于是分别增量后变为了 1,所以两个队列依序写入值都是 1,所以不是线程安全的。
    所以 atomic通过这种方法,在运行时保证 set,get方法的原子性。仅仅是保证了set,get方法的原子性。
    但是self.intA = self.intA + 1这个表达式并不是原子操作。所以线程是不安全的。所以仅仅使用atomic并不能保证线程安全。

     

    解决的办法应该是增加颗粒度,将读写两个操作合并为一个原子操作,从而解决写入过期数据的问题。
     1 objcos_unfair_lock_t unfairLock;
     2 - (void)competition {
     3 self.intSource = 0;
     4  
     5 unfairLock = &(OS_UNFAIR_LOCK_INIT);
     6 dispatch_async(queue1, ^{
     7 for (int i = 0; i < 10000; i++) {
     8 os_unfair_lock_lock(unfairLock);
     9 self.intSource = self.intSource + 1;
    10 os_unfair_lock_unlock(unfairLock);
    11 }
    12 });
    13  
    14 dispatch_async(queue2, ^{
    15 for (int i = 0; i < 10000; i++) {
    16 os_unfair_lock_lock(unfairLock);
    17 self.intSource = self.intSource + 1;
    18 os_unfair_lock_unlock(unfairLock);
    19 }
    20 });
    21 }
    在接下来的文章里会分别去讲解用法

     

  • 相关阅读:
    02-35 scikit-learn库之支持向量机
    C#当中的out关键字(借鉴于CSDN)
    Uploadify上传大文件
    EF-基础用法
    第一节:EasyUI样式,行内编辑,基础知识
    Compute和Linq的Field使用
    leetcode-15. 三数之和-OK
    C#启动时全屏显示窗体...
    C#启动时全屏显示窗体...
    leetcode-1117. H2O 生成
  • 原文地址:https://www.cnblogs.com/junhuawang/p/13529751.html
Copyright © 2011-2022 走看看