@synchronized 在 MRC 中不起作用,我的应用程序在多线程中崩溃
Posted
技术标签:
【中文标题】@synchronized 在 MRC 中不起作用,我的应用程序在多线程中崩溃【英文标题】:@synchronized not working in MRC,my app crash in multithreaded 【发布时间】:2014-09-16 02:19:13 【问题描述】://person.h
@interface Person : NSObject
@property(retain, nonatomic) NSString *indexStr;
- (instancetype)initWithIndex:(int)index;
- (void)print;
@end
//person.m
@implementation Person
- (instancetype)initWithIndex:(int)index
if (self = [super init])
_indexStr = [NSString stringWithFormat:@"%d",index];
NSLog(@"person init index:%d",index);
return self;
- (void)dealloc
self.indexStr = nil;
NSLog(@"person dealloc index:%@",self.indexStr);
[super dealloc];
@end
//vc.h
@property (retain, nonatomic) Person *person;
//vc.m
- (void)viewDidLoad
[super viewDidLoad];
_person = [[Person alloc] initWithIndex:-1];
for (int i = 0; i < 100000; i++)
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^
[self actionWrite:@(i)];
);
// [NSThread detachNewThreadSelector:@selector(actionRead) toTarget:self withObject:nil];
- (void)actionWrite:(NSNumber *)num
@synchronized(self)
self.person = [[[Person alloc] initWithIndex:[num intValue]] autorelease];
代码在 MRC 中。
它会在“actionWrith:”方法处崩溃。日志是:
2014-09-16 10:11:26.452 testThreadNoARC[1777:149948] person init index:357
2014-09-16 10:11:26.452 testThreadNoARC[1777:149961] person init index:358
2014-09-16 10:11:26.452 testThreadNoARC[1777:149947] person init index:359
2014-09-16 10:11:26.452 testThreadNoARC[1777:149937] person init index:360
2014-09-16 10:11:26.452 testThreadNoARC[1777:149944] person init index:361
2014-09-16 10:11:26.452 testThreadNoARC[1777:149950] person init index:362
2014-09-16 10:11:26.452 testThreadNoARC[1777:149941] person init index:363
2014-09-16 10:11:26.452 testThreadNoARC[1777:149959] person init index:364
2014-09-16 10:11:26.452 testThreadNoARC[1777:149955] person init index:365
2014-09-16 10:11:26.452 testThreadNoARC[1777:149951] person init index:366
2014-09-16 10:11:26.452 testThreadNoARC[1777:149958] person init index:367
2014-09-16 10:11:26.466 testThreadNoARC[1777:149975] person init index:368
2014-09-16 10:11:26.466 testThreadNoARC[1777:149964] person init index:369
2014-09-16 10:11:26.466 testThreadNoARC[1777:149971] person init index:370
2014-09-16 10:11:26.466 testThreadNoARC[1777:149863] *** -[CFString release]: message sent to deallocated instance 0x7fdc5bec77b0
它每次都在线程 1 崩溃,我不知道为什么会这样。 我认为 Person 对象已被释放,可能会再次释放以使崩溃。 但每次我运行代码时,它的崩溃日志都是一样的。 相同的代码在 ARC 上运行良好。
【问题讨论】:
【参考方案1】:您的 Person
初始化程序中有这一行:
_indexStr = [NSString stringWithFormat:@"%d",index];
stringWithFormat:
消息返回一个自动释放的值。您将其直接存储到由 retain
属性管理的实例变量中。由于您绕过了 setter,因此 setter 没有机会保留它。一旦自动释放池被耗尽,字符串就会被释放。由于您从未保留它,因此系统会取消分配它。现在_indexStr
是一个悬空指针。
稍后,在-[Person dealloc]
中,您可以这样做:
self.indexStr = nil;
由于indexStr
是retain
属性,它的setter 看起来像这样:
- (void)setIndexStr:(NSString *)value
NSString *oldValue = _indexStr;
[value retain];
_indexStr = value;
[oldValue release];
这意味着当设置器执行[oldValue release]
时,它会将release
发送到那个悬空指针。这就是你崩溃的地方。
最好的办法是停止使用 MRC 并开始使用 ARC。
在 MRC 下,您可以通过多种方式在 Person
初始化程序中正确保留字符串。这些都可以:
_indexStr = [[NSString stringWithFormat:@"%d",index] retain];
// or
self.indexStr = [NSString stringWithFormat:@"%d",index]
// or
_indexStr = [[NSString alloc] initWithFormat:@"%d", index];
【讨论】:
【参考方案2】:您没有保留用于_indexStr
的字符串。变化:
_indexStr = [NSString stringWithFormat:@"%d",index];
到:
_indexStr = [[NSString stringWithFormat:@"%d",index] retain];
【讨论】:
以上是关于@synchronized 在 MRC 中不起作用,我的应用程序在多线程中崩溃的主要内容,如果未能解决你的问题,请参考以下文章
窗口挂钩在 Windows 7 中不起作用,但在 Windows xp 中不起作用
为啥 heightForHeaderInSection 在 iOS 4.3 中不起作用?
为啥 IOCP 在 BeginExecuteReader 中不起作用