iOS面试题(每日一更)2020.6.2

一、讲一下atomic的实现机制;为什么不能保证绝对的线程安全(最好可以结合场景来说)?

atomic是在setter和getter方法里会使用自旋锁spinlock_t来保证setter方法和getter方法的线程的安全。可以看做是getter方法获取到返回值之前不会执行setter方法里的赋值代码。如果不加atomic,可能在getter方法读取的过程中,再别的线成立发生setter操作,从而出现异常值。

加上atomic后,setter和getter方法是线程安全的,原子性的,但是出了getter方法和setter方法后就不能保证线程安全了

@property (atomic, strong) NSArray*                arr;
//thread A
for (int i = 0; i < 10000; i ++) {
    if (i % 2 == 0) {
        self.arr = @[@"1", @"2", @"3"];
    }
    else {
        self.arr = @[@"1"];
    }
}

//thread B
for (int i = 0; i < 100000; i ++) {
    if (self.arr.count >= 2) {
        NSString* str = [self.arr objectAtIndex:1];
    }
}

上面的例子线程B里面可能会因为数组越界而引起crash,因为加入在B线程里判断self.arr.count >= 2的时候数组是self.arr = @[@“1”, @“2”, @“3”];但是当调用[self.arr objectAtIndex:1]可能self.arr的值已经在线程A里被更改为了@[@“1”],此时数组越界了。因此,虽然self.arr是atomic的,还是会出现线程安全问题。

思路:
automatic 从名字翻译上来看是原子性,原子的特点在编程领域的理解是最小的,不可分割的;
要了解它的实现机制,可以先从他的功能上探索,automatic一般是用来修饰属性的,而属性有两个基本的方法,setter 和 getter 方法,那么它的实现机制很可能就是作用于这两个方法,到这里基本上就可以触碰到automatic的实现机制的核心了;他是为了线程安全而设定的,线程安全的实现有多种方式:线程锁、信号量机制等,最常见的就是加锁了,而automatic 使用的就是加锁,具体是怎么加锁的,这里不考虑,加锁的目的当然是为了线程安全,那么具体是怎样的线程安全,通过其他的渠道了解到,这里的线程安全仅仅是 setter和getter方法不能同时操作,这在一定程度是确实做到了线程安全。
然而实际的多线程的编程过程中,在操作可变变量的时候,不同的线程由于时序的不同,会导致数组越界等灾难性的问题。

你可能感兴趣的:(iOS)