线程安全是在上下文中的安全

236 阅读1分钟
  • 关于"线程安全"的问题是,任何东西本身都不是"线程安全"。线程安全"只能在给定的上下文中确定,其中"线程安全"意味着尽管可能有多个线程,但仍然可以确保整个上下文的正确操作。例如,可变数组的特定实现可以说是真空中的"线程安全",因为人们永远不会访问内部不一致的数据,但如果条目没有与它引用的外部数据同步维护,这就毫无意义。这种同步只能在外部进行。

原子性解决的问题

- (NSNumber *)count {
    NSNumber *count;
    @synchronized(self) {
        count = [_count retain]; // +1
    }
    return [count autorelease]; // delayed -1
}

- (void)setCount:(NSNumber *)count {
    id oldValue;
    @synchronized(self) {
        oldValue = _count;
        _count = [count retain];
    }
    [oldValue release];
}

以上代码为设置原子性的属性的setter和getter原理差不多,线程A和线程B在设置属性时,等一条线程操作完成后,另一条线程才会执行。

非原子属性的setter方法中,线程A和线程B可能同时执行写入时,那线程A可能获取的是线程B中的oldValue或newValue,存在安全隐患。例如,两个操作都获取的是旧值,那么旧值会执行两次release,导致过度释放崩溃。

原子性不能避免的问题

多个线程同步获取整型属性并执行+1时,不同的线程可能都是得到旧值然后执行+1,那么最终的整型值不会是期望的结果。

此类风险的问题在特定上下文中会出现