iOS-多线程03-多线程知识点补充

在上一篇文章中,我们主要了解了多线程安全隐患,以及它的解决方案。其中,我们有了解到自旋锁和互斥锁,这两种经常用到的锁。这里有一个大致的总结,看看这两个锁在什么情况下比较合适:

1、什么情况使用自旋锁比较划算?
预计线程等待锁的时间很短
加锁的代码(临界区)经常被调用,但竞争情况很少发生
CPU资源不紧张
多核处理器
什么情况使用互斥锁比较划算?
2、预计线程等待锁的时间较长
单核处理器
临界区有IO操作
临界区代码复杂或者循环量大
临界区竞争非常激烈

接下来,我们再看另一个知识点,是关于读写安全方面的知识,首先我们来认识下atomic这个修饰符,在iOS这个修饰符的作用就是保证属性setter、getter的原子性操作,相当于在getter和setter内部加了线程同步的锁,它能保证在单个读和写的过程中是安全的,但是它并不能保证使用属性的过程是线程安全的。
这里,我们就针对这个使用属性过程的线程安全问题来看下,首先,我们需要了解方案的具体要求。大致如下:
1、同一时间,只能有1个线程进行写的操作。
2、同一时间,允许有多个线程进行读的操作。
3、同一时间,不允许既有写的操作,又有读的操作。
总结一句话的意思,就是“多读单写”,就是可以多条线程同时读取,但是在写入的时候,只能有一条线程在操作这个属性。iOS的常用实现方案有:
1、pthread_rwlock:读写锁
2、dispatch_barrier_async:异步栅栏
先来看看C语言中的读写锁pthread_rwlock的使用:

- (void)demo {
    
    pthread_rwlock_init(&_lock, NULL);
    
    dispatch_queue_t queue = dispatch_get_global_queue(0, 0);
    
    for (int i = 0; i < 10; i++) {
        dispatch_async(queue, ^{
            [self read];
        });
        dispatch_async(queue, ^{
            [self write];
        });
    }
}

- (void)read {
    pthread_rwlock_rdlock(&_lock);
    sleep(1);
    NSLog(@"read");
    pthread_rwlock_unlock(&_lock);
}

- (void)write
{
    pthread_rwlock_wrlock(&_lock);
    sleep(1);
    NSLog(@"write");
    pthread_rwlock_unlock(&_lock);
}

- (void)dealloc {
    pthread_rwlock_destroy(&_lock);
}


打印结果如下图:


image.png

我们可以很清楚的发现,只有在read操作的时候,是有多条线程同时打印的,任何write操作,都是会有1秒钟的间隔。
接下来,我们来看看异步栅栏操作:

- (void)demo {

    dispatch_queue_t queue = dispatch_queue_create("rw_queue", DISPATCH_QUEUE_CONCURRENT);

    for (int i = 0; i < 10; i++) {
        dispatch_async(queue, ^{
            [self read];
        });
        
        dispatch_async(queue, ^{
            [self read];
        });
        
        dispatch_async(queue, ^{
            [self read];
        });
        
        dispatch_barrier_async(queue, ^{
            [self write];
        });
    };
}

- (void)read {
    sleep(1);
    NSLog(@"read");
}

- (void)write
{
    sleep(1);
    NSLog(@"write");
}

打印结果如下:


image.png

也是我们所希望看到的结果。
不过这里有个必要的点,我们需要了解下,就是创建的queue必须是自定义的DISPATCH_QUEUE_CONCURRENT,如果是自定义串行队列或者直接使用全局并发队列,那么dispatch_barrier_async这个函数等同于dispatch_async!
以上就是这次对多线程知识点总结的补充内容!

©著作权归作者所有,转载或内容合作请联系作者
【社区内容提示】社区部分内容疑似由AI辅助生成,浏览时请结合常识与多方信息审慎甄别。
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

相关阅读更多精彩内容

  • 一、简介:多线程在之前进行过一篇详细的基础博客 iOS多线程 二、多线程的基础知识回顾 1.1、iOS中的常见多线...
    IIronMan阅读 4,507评论 0 4
  • Q:为什么出现多线程? A:为了实现同时干多件事的需求(并发),同时进行着下载和页面UI刷新。对于处理器,为每个线...
    幸福相依阅读 5,563评论 0 2
  • 前言 iOS开发中由于各种第三方库的高度封装,对锁的使用很少,刚好之前面试中被问到的关于并发编程锁的问题,都是一知...
    喵渣渣阅读 9,167评论 0 33
  • 1. iOS中的互斥锁 在编程中,引入对象互斥锁的概念,来保证共享数据操作的完整性。每个对象都对应于一个可称为“互...
    欢博阅读 4,457评论 0 1
  • 60秒学演讲,你会每天不一样,坚持日记,记录自己精彩人生!大家好,我是龙兄老师的迷弟,杨帆! 今天中午跟朋友一起吃...
    杨帆_cc94阅读 4,046评论 0 0

友情链接更多精彩内容