iOS 多线程并发-锁

这个应该是全平台都会遇到的问题了。当某个对象会被多个线程修改的时候,有可能一个线程访问这个对象的时候另一个线程已经把它删掉了,导致 Crash。比较常见的是在网络任务队列里面,主线程往队列里面加入任务,网络线程同时进行删除操作导致挂掉。

例子

这个真要写比较完整的并发操作的例子就有点复杂了。

解决方法

    • 加锁
      • NSLock

        普通的锁,加锁的时候 lock,解锁调用 unlock。

        - (void)addPlayer:(Player *)player {
           if (player == nil) return;
                NSLock* aLock = [[NSLock alloc] init];
                [aLock lock];
        
                [players addObject:player];
        
                [aLock unlock];
           }
        }
        

        可以使用标记符 @synchronized 简化代码:

        - (void)addPlayer:(Player *)player {
           if (player == nil) return;
           @synchronized(players) {
              [players addObject:player];
           }
        }
        
      • NSRecursiveLock 递归锁

        使用普通的 NSLock 如果在递归的情况下或者重复加锁的情况下,自己跟自己抢资源导致死锁。Cocoa 提供了 NSRecursiveLock 锁可以多次加锁而不会死锁,只要 unlock 次数跟 lock 次数一样就行了。

      • NSConditionLock 条件锁

        多数情况下锁是不需要关心什么条件下 unlock 的,要用的时候锁上,用完了就 unlock 就完了。Cocoa 提供这种条件锁,可以在满足某种条件下才解锁。这个锁的 lock 和 unlock, lockWhenCondition 是随意组合的,可以不用对应起来。

      • NSDistributedLock 分布式锁

        这是用在多进程之间共享资源的锁,对 iOS 来说暂时没用处。

    • 无锁
      放弃加锁,采用原子操作,编写无锁队列解决多线程同步的问题。酷壳有篇介绍无锁队列的文章可以参考一下:无锁队列的实现

    • 使用其他备选方案代替多线程:Operation Objects, GCD, Idle-time notifications, Asynchronous functions, Timers, Separate processes。
posted @ 2014-04-23 13:18  勿忘初心,方得始终  阅读(508)  评论(0编辑  收藏  举报