iOS 多线程并发-锁

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

例子

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

解决方法

    • 加锁
      • 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 来讲暂时没用处。线程

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

    • 使用其余备选方案代替多线程:Operation Objects, GCD, Idle-time notifications, Asynchronous functions, Timers, Separate processes。
相关文章
相关标签/搜索