Dose objc_release / objc_retain 线程安全吗?

Dose objc_release / objc_retain thread safe?

一个Class属性,如:

@interface TestModel
@property (nonatomic, copy) NSString *testStr;
@end 

在主线程:

for (model in modellist) {
    if ((!model.testStr || ![model.testStr isKindOfClass:[NSString class]] || model.testStr.length == 0)) {
         NSLog(@"empty str");
    }
    NSLog(@"not empty str");
}

在后台线程:

for (model in modellist) {
    model.testStr = anotherStringFromAlloc
}

主要thread:Only阅读属性

后台线程:写入属性内容

这个线程安全吗?

看了一些源码后,我还有一个问题是: objc_retain 和 objc_release 相同的对象是线程安全的吗?

正如 Petesh 指出的那样,这个问题大部分在 thread-safe retain/release 中得到了回答,但我认为只是在那里重复会错过回答您的具体问题。

您已明确要求此 属性 不是 是线程安全的:

@property (nonatomic, copy) NSString *testStr;

默认行为是atomic,这使得在不同线程上读写指针(不改变对象)是安全的。您已标记此 nonatomic,这会禁用该行为。有关这方面的更多信息,请参阅 atomic.

上的 bbum 相当 canonical answer

不过,您的代码也是一个很好的例子,它说明了仅依靠原子读取来使代码“线程安全”是如何出错的。此行非常不安全:

if ((!model.testStr || ![model.testStr isKindOfClass:[NSString class]] || model.testStr.length == 0)) {

这使得 model.testStr 的三个独立读取。即使使用 atomic,如果您可能在另一个线程上修改它,也不能保证它们是同一个对象。您测试 class 的事实表明 testStr 可能不是 NSString。如果是这样,那么 model.testStr.length 可能会因“不响应选择器”而崩溃。如果您在 if 块内使用 model.testStr,那么它也可能与您测试的值不同。