First look at the code:
- (void) viewdidload {[Super viewdidload]; Self.teststr=@"String Initial complete"; [Self performselector: @selector (CHANGESTR) withobject:nil Afterdelay:0.5]; Dispatch_async (Dispatch_get_global_queue (Dispatch_queue_priority_high,0), ^{NSLog (@"before sleep%@", SELF.TESTSTR); Sleep (3); NSLog (@"After sleep%@", SELF.TESTSTR); });}- (void) changestr{Self.teststr=@"String has changed";}
Execution Result:
£ º40.525 threadsafety test [49097:11809626 ] Before sleep String initialcomplete-all:11 :43.598 thread Safety test [49097:11809626] After sleep String have changed
It is found that in asynchronous execution, if the teststr changes, the teststr of the async line thread will change so that there is no guarantee that the asynchronous operation is exclusive to the resource.
If you create a str in an asynchronous block, the following code is assigned:
- (void) viewdidload {[Super viewdidload]; Self.teststr=@"String Initial complete"; [Self performselector: @selector (CHANGESTR) withobject:nil Afterdelay:0.5]; Dispatch_async (Dispatch_get_global_queue (Dispatch_queue_priority_high,0), ^{nsstring*str =Self.teststr; NSLog (@"before sleep%@", str); Sleep (3); NSLog (@"After sleep%@", str); });}- (void) changestr{Self.teststr=@"String has changed";}
Execution Result:
£ º09.785 threadsafety test [49319:11822894 ] Before sleep String initialcomplete-all:15 :12.786 thread Safety test [49319:11822894] After sleep String initial complete
The new string will not be affected by external changes, but if the SELF.ASSTR has been turned into a wild pointer at this time of assignment, then the operation behind it will still go wrong, although it is not so easy to appear.
How to prevent this situation, you can look at the following code:
- (void) viewdidload {[Super viewdidload]; Self.teststr=@"String Initial complete"; [Self performselector: @selector (CHANGESTR) withobject:nil Afterdelay:0.5]; __weak __typeof (self.teststr) weakstring=Self.teststr; Dispatch_async (Dispatch_get_global_queue (Dispatch_queue_priority_high,0), ^{__strong __typeof (weakstring) strongstring=weakstring; if(strongstring) {NSLog (@"before sleep%@", strongstring); Sleep (3); NSLog (@"After sleep%@", strongstring); } });}- (void) changestr{Self.teststr=@"String has changed";}
Execution Result:
£ º40.320 threadsafety test [49541:11835480 ] Before sleep String initialcomplete-all:18 :43.388 thread Safety test [49541:11835480] After sleep String initial complete
Weakstring will be set to nil when the SELF.ASSTR is released, if not nil, to ensure that the object is retain in the full cycle of the block call, if the execution of the preemption to Strongstring will continue and produce the same value if strongstring executes to is nil, then the block cannot be executed correctly before it is returned, so there is no previous problem.
You can also use locks to guarantee that multiple threads will not be changed during operation on a single copy of the resource
#import "ViewController.h"#include<pthread.h>@interfaceViewcontroller () {pthread_mutex_t _mutex;} @property (nonatomic, copy) NSString*Teststr;@end@implementationViewcontroller- (void) viewdidload {[Super viewdidload]; Pthread_mutex_init (&_mutex, NULL); Self.teststr=@"String Initial complete"; [Self performselector: @selector (CHANGESTR) withobject:nil Afterdelay:0.5]; Dispatch_async (Dispatch_get_global_queue (Dispatch_queue_priority_high,0), ^{Pthread_mutex_lock (&_mutex); NSLog (@"before sleep%@", SELF.TESTSTR); Sleep (3); NSLog (@"After sleep%@", SELF.TESTSTR); Pthread_mutex_unlock (&_mutex); });}- (void) changestr{Pthread_mutex_lock (&_mutex); Self.teststr=@"string has changed"; Pthread_mutex_unlock (&_mutex);}- (void) dealloc{Pthread_mutex_destroy (&_mutex);}@end
Execution Result:
2016 -10 - 14 09 : : 57.194 thread safety test [49824 : 11850779 2016 -10 - 14 09 : : 00.269 thread safety test [49824 : 11850779 ] After sleep String initial complete
Osspinlock is used in RAC to ensure thread safety, but several Apple engineers have swift-dev a spin lock bug in a message that discusses the thread safety of weak properties in the mailing list, e-mail address: https://lists.swift.org/ Pipermail/swift-dev/week-of-mon-20151214/000372.html. It is probably that different priority thread scheduling algorithms will have priority reversal problems, such as low-priority lock access to resources, high-priority attempts to access the waiting, when the low priority is not high priority so that the task cannot complete lock release. You can also take a look at the Reactiveco community discussion https://github.com/ReactiveCocoa/ReactiveCocoa/issues/2619
Originally Osspinlock is the highest performance lock, but because if not the same priority thread lock operation can not guarantee security, then Dispatch_semaphore and Pthread_mutex this second only to spin lock can be used as an alternative. I noticed that Facebook's Kvocontroller replaced all osspinlock with Pthread_mutex in a commit on May 17, 2016, but see this commithttps://github.com/ facebook/kvocontroller/commit/4f5c329b26f48b151eed82da085288763e2e1761. Pthread_mutex will be able to get a big boost in the new system's neutral, so consider this scenario.
iOS Developing thread safety issues