atomic的线程安全问题

1. atomic 与 nonatomic

atomic:

在默认情况下,由编译器所合成的方法会通过锁定机制确保其原子性, 避免在多线程情况下, 该变量的读写不同步的问题.
比如声明中加了atomic的函数, 在setter/getter 它时, 如果有多个线程同时调用setter的话,不会出现某一个线程执行完setter全部语句之前,另一个线程开始执行setter情况,相当于函数头尾加锁,可保证数据的完整性.

nonatomic:

如果该对象无需考虑多线程的情况,这个属性会让编译器少生成一些互斥代码,可提高效率, 减少性能消耗.
在多线程情况下, 如果当其中一个线程正在改写某属性值的时候,另外一个线程也许会突然闯入,把尚未修改好的属性值读取出来. 这时线程读取的属性值有可能不对.


2. atomic不一定是线程安全的

atomic只能保证读写安全,并不能保证线程安全.

@synchronized指令执行其他任何互斥锁都会执行的操作: 它可以防止不同的线程同时获取同一个锁。 但是,在这种情况下,您不必直接创建互斥锁或锁定对象。 相反,您只需使用任何Objective-C对象作为锁定标记,如下所示:

- (void)myMethod:(id)anObj {
    @synchronized(anObj) {
        // 此大括号之间的所有内容都由@synchronized指令保护.
    }
}

传递给@synchronized指令的对象是用于区分受保护块的唯一标识符。如果在两个不同的线程中执行上述方法,则在每个线程上为anObj参数传递一个不同的对象,每个线程都会锁定并继续处理而不被另一个线程阻塞。但是,如果在两种情况下传递相同的对象,则其中一个线程将首先获取锁,另一个会阻塞,直到第一个线程完成临界区。
作为预防措施,@synchronized代码块会隐式地向受保护的代码添加一个异常处理程序。如果引发异常,该处理程序会自动释放互斥锁。这意味着为了使用@synchronized指令,还必须在代码中启用Objective-C异常处理。如果不想由隐式异常处理程序引起额外开销,则应考虑在线程中使用lock来保证线程安全.

atomic对属性的读和写是原子性的,所以一个线程正在执行getter/setter,其他线程就得等待.

比如有A, B, C三个线程:

当A进行写操作,这时其他线程的读或者写操作会因为等该操作而等待. 即B在A写操作时在等待.
当A写操作结束, B才可进行写操作.
别的线程还能进行读写之外的其他操作, 如果C在A读操作之前release了该属性,A还可在C操作结束后对该属性进行读操作, 如果A这样做了, 那就会导致程序崩溃.

你可能感兴趣的:(ios)