My app crashed, suspected to be caused by multi-threaded operation of an attribute in a singleton object. So I wrote a small piece of code and successfully reproduced the problem, but I still couldn't understand it. I have defined the property as @property, which is atomic. Why does it still crash when accessed by multiple threads? Below is my code snippet:
Audio.h
@interface Audio : NSObject
@property NSString *audioName;
@property NSString *audioData;
@end
Audio.m
#import "Audio.h"
@implementation Audio
- (instancetype)init{
self = [super init];
if (self) {
_audioData = @"";
_audioName = nil;
}
return self;
}
@end
AudioManager.h
@interface AudioManager : NSObject
+(instancetype)shareInstance;
@property Audio *curAudio;
-(void) play;
-(void) clearCurAudio;
@end
AudioManager.m
#import "AudioManager.h"
@implementation AudioManager
static id sharedInstance = nil;
+(instancetype)shareInstance {
static dispatch_once_t predicate;
dispatch_once(&predicate, ^{
sharedInstance = [[self alloc] init];
});
return sharedInstance;
}
-(void) play {
NSLog(@"Current Audio name : %@",_curAudio.audioName);
NSLog(@"Current Audio name : %@",_curAudio.audioData);
NSLog(@"Current Audio name : %@",_curAudio.audioName);//crahed here!
NSLog(@"Current Audio name : %@",_curAudio.audioData);
}
-(void) clearCurAudio {
_curAudio = nil;
}
@end
- (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view.
dispatch_queue_t thread1 = dispatch_queue_create("queue1", nil);
dispatch_queue_t thread2 = dispatch_queue_create("queue2", nil);
dispatch_queue_t thread3 = dispatch_queue_create("queue3", nil);
dispatch_async(thread1, ^{
for (int i = 0; i < 1000; i++) {
Audio *newAudio = [[Audio alloc] init];
newAudio.audioName = @"na";
[[AudioManager shareInstance] setCurAudio:newAudio];
}
});
//
dispatch_async(thread2, ^{
for (int i = 0; i < 1000; i++) {
[[AudioManager shareInstance] play];
}
});
//
dispatch_async(thread3, ^{
for (int i = 0; i < 1000; i++) {
AudioManager * audioManager = [AudioManager shareInstance];
[[AudioManager shareInstance] clearCurAudio];
}
});
}
Here is the crash EXC_BAD_ACCESS: enter image description here