多线程调用引起的问题

作者: _Thinking_ | 来源:发表于2016-08-13 17:24 被阅读96次

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

    先有问题的代码:

    
    @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 的写法,只是很少会直接写到函数里面。

    相关文章

      网友评论

        本文标题:多线程调用引起的问题

        本文链接:https://www.haomeiwen.com/subject/erxysttx.html