Reputation: 573
A Class Property, Such as:
@interface TestModel
@property (nonatomic, copy) NSString *testStr;
@end
At main Thread:
for (model in modellist) {
if ((!model.testStr || ![model.testStr isKindOfClass:[NSString class]] || model.testStr.length == 0)) {
NSLog(@"empty str");
}
NSLog(@"not empty str");
}
At BackGround Thread:
for (model in modellist) {
model.testStr = anotherStringFromAlloc
}
At main thread:Only read property
At backGround thread: Write property content
Is this thread safe?
After read some source code, I have another question is: Dose objc_retain and objc_release same obj is thread safe ?
Upvotes: 1
Views: 152
Reputation: 299275
As Petesh notes, this question is mostly answered in thread-safe retain/release, but I think just duping there will miss answering your specific problem.
You've explicitly asked for this property not to be thread-safe:
@property (nonatomic, copy) NSString *testStr;
The default behavior is atomic
, which make it safe to read and write the pointer (not mutate the object) on different threads. You've marked this nonatomic
, which disables that behavior. For more on this, see bbum's fairly canonical answer on atomic
.
Your code, though, is also a good example of how relying on atomic reads alone to make code "thread-safe" can go wrong. This line is very unsafe:
if ((!model.testStr || ![model.testStr isKindOfClass:[NSString class]] || model.testStr.length == 0)) {
This makes three separate reads of model.testStr
. Even with atomic
, there's no promise that these are the same object if you might modify this on another thread. The fact that you test the class suggests that testStr
might be something other than an NSString. If so, then model.testStr.length
may crash with "does not respond to selector." If you use model.testStr
inside the if
block, then that may also be a different value than you tested.
Upvotes: 1