多线程调用引起的问题

今天发现一个老问题引起的崩溃,记录一下。

先有问题的代码:


@implementation LogicHandle

- (instancetype)init
{
    if (self = [super init]) {
        [[NSNotificationCenter defaultCenter] addObserver:self
                                                 selector:@selector(onNotification)
                                                     name:@"kLogicNotification" object:nil];
    }
    
    return self;
}

- (void)dealloc
{
    [[NSNotificationCenter defaultCenter] removeObserver:self];
}

- (void)onNotification
{
    [self showLog];
    [self showLog];
    [self showLog];
    [self showLog];
}

- (void)showLog
{
    NSLog(@"%@", self);
}

@end
//Post通知代码
- (void)postNotificationInBackground
{
    dispatch_sync(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
        [[NSNotificationCenter defaultCenter] postNotificationName:kLogicNotification object:nil];
    });
}


常规的通知接收模型大致都是这样格式,但是这种方式在处理多线程的调用时会有问题。

由于PostNotification是在另一个线程的,所以 onNotification 也会在另一个线程执行。 这个时候很多人会认为是不是多线程访问对象引起的崩溃?那加个锁可以解决问题吗?

- (void)onNotification
{
    @synchronized (self) {
        xxx;
        xxx;
    }
}

没错, 多线程访问数据时会有问题,但很明显这里只是输出一下 self, 并没有涉及到数据的修改,所以这种方式的加锁是不能解决问题的。

原因:

当后台线程在执行 onNotification 方法的时候,执行到一半,其他线程把对象释放了。

解决方法:

  • 保证在同一线程发通知
  • 如果要支持多线程调用,可以用 "强引用" 确保对象不被释放。
- (void)mutithread_message
{
    __strong __typeof(self) strongSelf = self;
    [strongSelf op];
}

这种其实就是 block 里面常规的 weak-strong 的写法,只是很少会直接写到函数里面。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容