0

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 ?

waitianlou
  • 563
  • 3
  • 15
  • 1
    The atomicity is there to allow you to safely use the returned `NSString` from the property without fear of it being released out from under you as a result of an assignment. If you're asking if the code is 'thread safe', under the very limited use you're using in this example code, it *will work*, but if you want to make use of the returned property for anything other than a `NULL` check, it needs to be atomic to keep it safe. In relation to your other question - [it's already answered here](https://stackoverflow.com/questions/6512540/thread-safe-retain-release). – Anya Shenanigans Jan 05 '22 at 13:34

1 Answers1

1

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.

Rob Napier
  • 286,113
  • 34
  • 456
  • 610
  • Helped me a lot,Specifically pointed out that atmoic only ensure getter thread safe,there is no guarantee that logic is correct – waitianlou Jan 06 '22 at 04:16