美文网首页
iOS开发线程锁

iOS开发线程锁

作者: 科技农民工 | 来源:发表于2019-07-10 17:05 被阅读0次

前言

多线程是现在每个开发必定知道的。这哥们(多线程)是用来干啥的?举个例子拿单线程来说,单线程就是你写的代码一步一步执行,完全按照顺序执行,科技一步一步进步,现在CPU核心数越来越多,多线程也就成为了现在每个程序员必回的一个知识点。但是使用多线程优点就不多说了。要说都是优点没缺点,这纯瞎说,他的弊端就是资源抢占问题,开辟多条线程占用一定的资源(主线程一般1MB ,其他线程512kb,一般建议同时最多开三条线程比较合理)。关于资源抢占问题下面就举个例子:在使用多线程的时候多个线程可能会访问同一块资源,这样就很容易引发数据错乱和数据安全等问题。解决资源争用,最直接的想法是引入锁,对并发读写的数据进行保护,保证每次只有一个线程访问这一块资源。
  锁是最常用的同步工具:一块公共资源在同一个时间只能允许被一个线程访问,比如一个线程A进入加锁资源之后,由于已经加锁,另一个线程B就无法访问,只有等待前一个线程A执行完后解锁,B线程才能访问加锁资源。

为什么需要锁?
 以常见的火车站卖票为例,假设有20张票,有两个窗口同时售票:

- (void)ticketTest{
    self.ticketsCount = 20;
    dispatch_queue_t queue = dispatch_get_global_queue(0, 0);
    // 线程1
    dispatch_async(queue, ^{
        for (int i = 0; i < 10; i++) {
                [self sellingTickets];//多线程售票
            }
    });
    // 线程2
    dispatch_async(queue, ^{
        for (int i = 0; i < 10; i++) {
                [self sellingTickets];//多线程售票
            }
    });
}

- (void)sellingTickets{
    NSInteger oldMoney = self.ticketsCount;
    sleep(0.2);
    oldMoney -= 1;
    self.ticketsCount = oldMoney;
    NSLog(@"当前剩余票数-> %ld", oldMoney);
}

不加锁

2019-02-21 17:10:40.861358+0800 多线程测试[8167:20874670] 当前剩余票数-> 19
2019-02-21 17:10:40.861358+0800 多线程测试[8167:20874671] 当前剩余票数-> 19
2019-02-21 17:10:40.861723+0800 多线程测试[8167:20874671] 当前剩余票数-> 18
2019-02-21 17:10:40.861723+0800 多线程测试[8167:20874670] 当前剩余票数-> 18
2019-02-21 17:10:40.861851+0800 多线程测试[8167:20874670] 当前剩余票数-> 17
2019-02-21 17:10:40.861961+0800 多线程测试[8167:20874670] 当前剩余票数-> 16
2019-02-21 17:10:40.861989+0800 多线程测试[8167:20874671] 当前剩余票数-> 16
2019-02-21 17:10:40.862066+0800 多线程测试[8167:20874670] 当前剩余票数-> 15
2019-02-21 17:10:40.862222+0800 多线程测试[8167:20874670] 当前剩余票数-> 14
2019-02-21 17:10:40.863234+0800 多线程测试[8167:20874671] 当前剩余票数-> 13
2019-02-21 17:10:40.863958+0800 多线程测试[8167:20874670] 当前剩余票数-> 12
2019-02-21 17:10:40.864225+0800 多线程测试[8167:20874671] 当前剩余票数-> 11
2019-02-21 17:10:40.864529+0800 多线程测试[8167:20874670] 当前剩余票数-> 10
2019-02-21 17:10:40.865159+0800 多线程测试[8167:20874671] 当前剩余票数-> 9
2019-02-21 17:10:40.865498+0800 多线程测试[8167:20874670] 当前剩余票数-> 8
2019-02-21 17:10:40.865777+0800 多线程测试[8167:20874671] 当前剩余票数-> 7
2019-02-21 17:10:40.866747+0800 多线程测试[8167:20874670] 当前剩余票数-> 6
2019-02-21 17:10:40.866970+0800 多线程测试[8167:20874671] 当前剩余票数-> 5
2019-02-21 17:10:40.867402+0800 多线程测试[8167:20874671] 当前剩余票数-> 4
2019-02-21 17:10:40.867879+0800 多线程测试[8167:20874671] 当前剩余票数-> 3

不加锁时很明显数据发生了混乱。

iOS中都有哪些锁?

敲黑板,讲重点。
从大的方向讲有两种锁:

互斥锁

自旋锁。

这两种类型下分别有自己对应的锁: NSLock.png

互斥锁和自旋锁的对比:

这两种锁的相同点不必多说,都可以避免多线程访问同一个值发生混乱,重点说一下两种的不同点:

互斥锁:如果共享数据已经有其他线程加锁了,线程会进入休眠状态等待锁。一旦被访问的资源被解锁, 则等待资源的线程会被唤醒

自旋锁:如果共享数据已经有其他线程加锁了,线程会以死循环的方式等待锁,一旦被访问的资源被解锁, 则等待资源的线程会立即执行

自旋锁的特点:

自旋锁的性能高于互斥锁,因为响应速度快
自旋锁虽然会一直自旋等待获取锁,但不会一直占用CPU,超过了操作系统分配的时间片会被强制挂起
自旋锁如果不能保证所有线程都是同一优先级,则可能造成死锁。

因为以上的特点,自旋锁和互斥锁也有不同的使用场景:

多核处理器情况下: 如果预计线程等待锁的时间比较短,短到比线程两次切换上下文的时间还要少的情况下,自旋锁是更好的选择。
如果时间比较长,则互斥锁是比较好的选择。 单核处理器情况下: 不建议使用自旋锁。

从详细来分锁:

  • @synchronized

  • NSLock 对象锁

  • NSRecursiveLock递归锁

  • NSConditionLock 条件锁

  • pthread_mutex 互斥锁(C语言)

  • dispatch_semaphore 信号量实现加锁(GCD)

  • OSSpinLock 自旋锁

具体使用请移步google。

相关文章

  • iOS-锁

    iOS开发中知道的哪些锁? 哪个性能最差? 锁是线程编程同步工具的基础。iOS开发中常用的锁有如下几种: @syn...

  • 线程锁

    探讨iOS开发中各种锁使用NSCondition实现多线程同步 NSCondition是线程同步, 阻塞线程。 取...

  • iOS开发中的锁

    iOS开发中的锁 本人对锁没有深入理解,只是看了几篇文章,在这里做一下简单的总结。 iOS开发中,锁是用来解决线程...

  • iOS开发中常用的锁

    锁是线程编程同步工具的基础,在iOS开发中常用的锁有以下几种: @synchronized NSLock 对象锁 ...

  • 起底多线程同步锁(iOS)

    起底多线程同步锁(iOS) 起底多线程同步锁(iOS)

  • iOS开发线程锁

    前言 多线程是现在每个开发必定知道的。这哥们(多线程)是用来干啥的?举个例子拿单线程来说,单线程就是你写的代码一步...

  • iOS 锁的使用

    参考 demo 参考的文章:iOS开发中的11种锁以及性能对比多线程-线程安全 结论: 自旋锁性能 > 信号量 >...

  • OC--各种线程锁

    参考:正确使用多线程同步锁@synchronized()iOS中的锁iOS多线程安全详解iOS 常见知识点(三):...

  • 多线程 (三)iOS中的锁

    ios 多线程--锁

  • iOS-知识点

    五个案例让你明白GCD死锁:http://ios.jobbole.com/82622/ iOS开发中多线程间关于锁...

网友评论

      本文标题:iOS开发线程锁

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