美文网首页
nonatomic和atomic探究

nonatomic和atomic探究

作者: 傲骨天成科技 | 来源:发表于2021-06-25 11:24 被阅读0次

    这两个关键字面试经常被问到,每次回答的貌似对了,但是又貌似不是特别理解,因此为又研究了一遍,特此做个记录。

    结论

    nonatimic、atomic读写安全,但效率低,不是绝对的安全,比如操作数组,增加或移除,这种情况可以使用互斥锁来保证线程安全(atomic并不能保证多线程安全,只能保证数据的完整性,完整性是,使用者总能取到完整的值,不存在给已经释放的对象设置值)
    atomic所说的线程安全只是保证了getter和setter存取方法的线程安全,并不能保证整个对象是线程安全的。
    是给set和get方法加了锁

    一、使用nonatomic崩溃

    #import "ViewController.h"
    
    @interface ViewController ()
    
    @property (nonatomic,copy) NSString *name;
    
    @end
    
    @implementation ViewController
    
    - (void)viewDidLoad {
        [super viewDidLoad];
    
        
        dispatch_queue_t queue = dispatch_queue_create("abcde", DISPATCH_QUEUE_CONCURRENT);
        for (int i = 0 ; i < 10000; i ++) {
            dispatch_async(queue, ^{
                NSLog(@"%@",[NSThread currentThread]); 
                self.name = [NSString stringWithFormat:@"我%d",i]; // 会新创建一个新的字符串对象
            });
        }
    
    }
    
    
    @end
    
    分析:

    属性的set方法,ARC环境下,如果有两个线程同时给属性设置值时,就会同时把属性给release释放两次。过渡释放造成崩溃

    属性是atomic时,不会崩溃,里面加了同步锁,set,get方法只能串行执行。

    二、nonatimic、atomic不是线程安全的

    ///
    @property (nonatomic, assign) int slice;
    
        self.slice = 0;
        NSLog(@"%p",&_slice);
        dispatch_queue_t queue = dispatch_queue_create("TestQueue", DISPATCH_QUEUE_CONCURRENT);
        dispatch_async(queue, ^{
            for (int i=0; i<10000; i++) {
                
                self.slice = self.slice + 1;
            }
        });
        dispatch_async(queue, ^{
            for (int i=0; i<10000; i++) {
                
    
                self.slice = self.slice + 1;
            }
        });
    
        
        dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(0.5 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
            
            NSLog(@"%p",&self->_slice);
            NSLog(@"%d",self.slice);
        });
    
    分析

    eg1:如果定义属性NSInteger i是原子的,对i进行i = i + 1操作就是不安全的; 因为原子性只能保证读写安全,而该表达式需要三步操作:
    1、读取i的值存入寄存器;
    2、将i加1;
    3、修改i的值;
    如果在第一步完成的时候,i被其他线程修改了,那么表达式执行的结果就与预期的不一样,也就是不安全的

    结果可能是[10000,20000]之间的某个值,所以atomic是线程不安全的。但是线程安全还有除了读写的其他操作,比如:当一个线程正在get/set时,另一个线程同时进行release操作,可能会直接crash。很明显atomic的读写锁不能保证线程安全。

    相关文章

      网友评论

          本文标题:nonatomic和atomic探究

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