美文网首页
iOS-多线程03-多线程知识点补充

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

作者: IBigLiang | 来源:发表于2019-09-27 19:14 被阅读0次

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

    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!
    以上就是这次对多线程知识点总结的补充内容!

    相关文章

      网友评论

          本文标题:iOS-多线程03-多线程知识点补充

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