原子属性

  • 原子属性(线程安全),是针对多线程设计的,是默认属性
  • 多个线程在写入原子属性时(调用 setter 方法),能够保证同一时间只有一个线程执行写入操作
  • 原子属性是一种单(线程)写多(线程)读的多线程技术
  • 原子属性的效率比互斥锁高,不过可能会出现脏数据
  • 在定义属性时,必须显示地指定 nonatomic,否则默认为atomic

多线程——atomic nonatomic的区别


  • 原子性atomic ,默认属性,编译器会在property上自动添加原子锁
    非原子性nonatomic,不考虑多线程情况时使用,提高效率
  • 原子属性内部的锁是 自旋锁自旋锁的执行效率比互斥锁高
  • atomic本质上就是给get/set方法加锁,即原子锁,以避免线程A还没执行完setter,线程B又开始执行的,导致读取数据错误的问题。

  • atomic一定是线程安全的么?
    不一定,首先atomic的释义是原子性,并不是线程安全。原子性这个概念表示一个操作序列就像一个操作一样不被打断,而不像一个操作序列一样中间容许被打断。所以nonatomic一定是线程不安全的,但是atomic却不一定是线程安全的。

    • 假设线程A执行在对某属性get之前线程B release了该属性,会导致程序崩溃。


原子属性内部的锁是 自旋锁自旋锁的执行效率比互斥锁高

2.6.2自旋锁&互斥锁
1 、共同点
  • 都能够保证同一时间,只有一条线程执行锁定范围的代码

  2 、不同点
  • 互斥锁:如果发现有其他线程正在执行锁定的代码,线程会进入休眠状态,等待其他线程执行完毕,打开锁之后,线程会被唤醒
  • 自旋锁:如果发现有其他线程正在执行锁定的代码,线程会以死循环的方式,一直等待锁定代码执行完成。

  3 、结论
  • 自旋锁更适合执行非常短的代码
  • 无论什么锁,都是要付出代价



下面附上代码分析

1 、定义原子属性
@property (nonatomicstrongNSObject *obj1;
@property (atomicstrongNSObject *obj2;

// 模拟原子属性
@property (atomicstrongNSObject *obj3;

2 、模拟原子属性
 如果重写了 atomic 属性的 setter方法,就必须重新 getter 方法。
 - 如果同时重写了 setter  getter 方法,苹果就不再提供_成员变量
 - @synthesize  合成指令,用处就是指定属性的 成员变量。

@implementation  ViewController
// 合成指令
@synthesize obj2 = _obj2 ;

- (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event{
     // 记录运行时间  开始和结束
    CFAbsoluteTime atatrt = CFAbsoluteTimeGetCurrent();
 
     for  ( int   i =  0 ; i <  1000  * 1000 ; i++) {
        self.obj0 = [[NSObject alloc]init]; //创建对象  
    }
   
  // 记录结束时间
    
  CFAbsoluteTime  end =   CFAbsoluteTimeGetCurrent ();
   
   
  NSLog ( @" 非原子性 %f" ,end - atatrt);
   
   
   
   
  // 记录运行时间  开始和结束
     atatrt =
  CFAbsoluteTimeGetCurrent ();
   
   
  for  ( int   i =  0 ; i <  1000  * 1000 ; i++) {
         self . obj1  = [[ NSObject  alloc ] init ];
    }
   
  // 记录结束时间
     end = 
  CFAbsoluteTimeGetCurrent ();
   
   
  NSLog ( @" 原子性 %f" ,end - atatrt);
   
   
   
   
   
  // 记录运行时间  开始和结束
    atatrt =
  CFAbsoluteTimeGetCurrent ();
   
   
  for  ( int   i =  0 ; i <  1000  * 1000 ; i++) {
       
  self . obj2  = [[ NSObject  alloc ] init ];
    }
   
   
  // 记录结束时间
    end = 
  CFAbsoluteTimeGetCurrent ();
   
   
  NSLog ( @" 模拟原子性 %f" ,end - atatrt);
}


// 原子性属性  如果自己重新写 setter  方法就不会生成 getter 方法了
// 需要重写 get 方法
- (
void )setObj2:( NSObject  *)obj2{

   
  @synchronized ( self ) {
       
  _obj2  = obj2;
    }
}

- (
NSObject  *)obj2{

   
  return  _obj2 ;
}

附上代码

1 、定义原子属性
@property (nonatomicstrongNSObject *obj1;
@property (atomicstrongNSObject *obj2;

// 模拟原子属性
@property (atomicstrongNSObject *obj3;

2 、模拟原子属性
 如果重写了 atomic 属性的 setter方法,就必须重新 getter 方法。
 - 如果同时重写了 setter  getter 方法,苹果就不再提供_成员变量
 - @synthesize  合成指令,用处就是指定属性的 成员变量。

@implementation  ViewController
// 合成指令
@synthesize obj2 = _obj2 ;

- (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event{
     // 记录运行时间  开始和结束
    CFAbsoluteTime atatrt = CFAbsoluteTimeGetCurrent();
 
     for  ( int   i =  0 ; i <  1000  * 1000 ; i++) {
        self.obj0 = [[NSObject alloc]init]; //创建对象  
    }
   
  // 记录结束时间
    
  CFAbsoluteTime  end =   CFAbsoluteTimeGetCurrent ();
   
   
  NSLog ( @" 非原子性 %f" ,end - atatrt);
   
   
   
   
  // 记录运行时间  开始和结束
     atatrt =
  CFAbsoluteTimeGetCurrent ();
   
   
  for  ( int   i =  0 ; i <  1000  * 1000 ; i++) {
         self . obj1  = [[ NSObject  alloc ] init ];
    }
   
  // 记录结束时间
     end = 
  CFAbsoluteTimeGetCurrent ();
   
   
  NSLog ( @" 原子性 %f" ,end - atatrt);
   
   
   
   
   
  // 记录运行时间  开始和结束
    atatrt =
  CFAbsoluteTimeGetCurrent ();
   
   
  for  ( int   i =  0 ; i <  1000  * 1000 ; i++) {
       
  self . obj2  = [[ NSObject  alloc ] init ];
    }
   
   
  // 记录结束时间
    end = 
  CFAbsoluteTimeGetCurrent ();
   
   
  NSLog ( @" 模拟原子性 %f" ,end - atatrt);
}


// 原子性属性  如果自己重新写 setter  方法就不会生成 getter 方法了
// 需要重写 get 方法
- (
void )setObj2:( NSObject  *)obj2{

   
  @synchronized ( self ) {
       
  _obj2  = obj2;
    }
}

- (
NSObject  *)obj2{

   
  return  _obj2 ;
}
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值