iOS atomic noatomic,copy strong的区别

249 阅读5分钟

一、# atomic 和nonatomic的区别

1、atomic

  • 对同一对象的set和get的操作是顺序执行的
  • 速度不快,因为要保证操作整体的完整性
  • 线程安全,需要消耗大量的资源来添加线程锁

atomic修饰的属性,系统生成的 getter/setter 会保证 get、set 操作的完整性,不受其他线程影响。比如,线程 A 的 getter 方法运行到一半,线程 B 调用了 setter:那么线程 A 的 getter 还是能得到一个完好无损的对象。

2、nonatomic

  • 更快
  • 如果有两个线程同时访问同一个属性,会出现无法预料的后果
  • 非线程安全,适合内存较小的移动设备

nonatomic修饰的属性,不做保持getter完整性保证,但在运行速度上要比atomic快

理解:
atomatic 修饰的属性age如果同时线程A调用setAge:A的话,同时线程B,线程C也在调用这个时候 各个线程将会依次进行,其他线程等待来保证整体的完整性。所以它的读写是安全的。但是如果这个时候[age release]的话这个时候会crash。因为release 不受属性的操作限制,所以是读写安全的,线程并不安全,这个需要我们开发者来确保。 noatomatic 修饰属性的如果是上面的那种情况,这个结果就无法预料因为他们会同时执行,本身也没有完整性的保障。

二、strong与copy的区别

浅拷贝:并不是拷贝对象的本身,而是对指向对象指针进行拷贝,改变原对象会影响新对象,从本质来说还是一个对象。这个对象只是对引用计数+1
深拷贝:直接拷贝生成一个新的对象,改变原有对象不会影响新的对象,在内存是出现了两个独立的对象。

strong:(浅拷贝) copy:(浅拷贝,当对象时是可变对象时,这个时候会进行深拷贝)

  1. 相当于对指向对象的指针进行复制,产生一个新的指向对象的指针
  2. 就有两个指针指向同一个对象;
  3. 这个对象销毁后,两个指针都应置空
  4. 对象引用计数+1

strong copy 的区别

1、当对象时不可变字符串的时候:

@property(nonatomic, strong) NSString *tempStr1;
@property (nonatomic, copy) NSString *tempStr2;
    NSString *str  = @"sorry,I get pregnant";
    self.tempStr1 = str;
    self.tempStr2 = str;

    NSLog(@"%@---%p",str,str);
    NSLog(@"%@---%p",self.tempStr1,self.tempStr1);
    NSLog(@"%@---%p",self.tempStr2,self.tempStr2);
    
    NSLog(@"======================================");

    str = @"oh,really,Its nothing to do with  me";
    NSLog(@"%@---%p",str,str);
    NSLog(@"%@---%p",self.tempStr1,self.tempStr1);
    NSLog(@"%@---%p",self.tempStr2,self.tempStr2);
    
    // 结果
    2022-08-09 15:22:49.784053+0800 Test[2062:1048030] sorry,I get pregnant---0x1004b4190
   2022-08-09 15:22:49.784125+0800 Test[2062:1048030] sorry,I get pregnant---0x1004b4190
   2022-08-09 15:22:49.784146+0800 Test[2062:1048030] sorry,I get pregnant---0x1004b4190
   
======================================================

  2022-08-09 15:22:49.784193+0800 Test[2062:1048030] oh,really,Its nothing to do with  me---0x1004b41f0 

  2022-08-09 15:22:49.784217+0800 Test[2062:1048030] sorry,I get pregnant---0x1004b4190 

  2022-08-09 15:22:49.784237+0800 Test[2062:1048030] sorry,I get pregnant---0x1004b4190 
  // 大家可以看下其实不论是strong 还是 copy 都是一样的。只是对指针进行了copy 值根本没有发生变化
  // 至于为什么重新赋值之后原来指针发生了变化是因为他指向了一个新的内存所以重新赋值发生了地址的变化,而我们的属性还是指向原来的地址。
    

对象时可变字符串的时候:

NSMutableString *str  = [NSMutableString stringWithString:@"sorry,I get pregnant"];

    self.tempStr1 = str;
    self.tempStr2 = str;
    NSLog(@"%@---%p",str,str);
    NSLog(@"%@---%p",self.tempStr1,**self**.tempStr1);
    NSLog(@"%@---%p",self.tempStr2,**self**.tempStr2);

    NSLog(@"======================================");
    
    [str setString: @"oh,really,Its nothing to do with  me"];

    NSLog(@"%@---%p",str,str);
    NSLog(@"%@---%p",self.tempStr1,self.tempStr1);
    NSLog(@"%@---%p",self.tempStr2,self.tempStr2);
    
    2022-08-09 15:55:15.833051+0800 Test[2089:1059139] sorry,I get pregnant---0x280da8b10
    2022-08-09 15:55:15.833123+0800 Test[2089:1059139] sorry,I get pregnant---0x280da8b10
   2022-08-09 15:55:15.833146+0800 Test[2089:1059139] sorry,I get pregnant---0x280da8c90

=====================================================

   2022-08-09 15:55:15.833195+0800 Test[2089:1059139] oh,really,Its nothing to do with  me---0x280da8b10 

   2022-08-09 15:55:15.833225+0800 Test[2089:1059139] oh,really,Its nothing to do with  me---0x280da8b10

   2022-08-09 15:55:15.833246+0800 Test[2089:1059139] sorry,I get pregnant---0x280da8c90
   
   // 这个时候大家会发现修饰可变字符串的时候 strong修饰的是指针地址是不变的
    

大家可以简单的理解就是:copy strong 如果修饰的是不可变字符串这个时候他们都是引用计数+1,属于浅拷贝,只是对指针的拷贝,如果是修饰的不可变字符串,strong依然是浅拷贝,而copy 则是深拷贝会对属性进行新的复制,属于一个全新的对象。 mutableCopy 不论修饰可变的还是不可变的对象都是深拷贝