这个应该是全平台都会遇到的问题了。当某个对象会被多个线程修改的时候,有可能一个线程访问这个对象的时候另外一个线程已经把它删掉了,致使 Crash。比较常见的是在网络任务队列里面,主线程往队列里面加入任务,网络线程同时进行删除操做致使挂掉。html
这个真要写比较完整的并发操做的例子就有点复杂了。shell
普通的锁,加锁的时候 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]; } }
使用普通的 NSLock 若是在递归的状况下或者重复加锁的状况下,本身跟本身抢资源致使死锁。Cocoa 提供了 NSRecursiveLock 锁能够屡次加锁而不会死锁,只要 unlock 次数跟 lock 次数同样就好了。并发
多数状况下锁是不须要关心什么条件下 unlock 的,要用的时候锁上,用完了就 unlock 就完了。Cocoa 提供这种条件锁,能够在知足某种条件下才解锁。这个锁的 lock 和 unlock, lockWhenCondition 是随意组合的,能够不用对应起来。分布式
这是用在多进程之间共享资源的锁,对 iOS 来讲暂时没用处。线程
无锁
放弃加锁,采用原子操做,编写无锁队列解决多线程同步的问题。酷壳有篇介绍无锁队列的文章能够参考一下:无锁队列的实现code