iOS中各种锁的性能对比

作者: o0阿拉斯加的狗0o | 来源:发表于2016-11-27 23:34 被阅读757次

    自旋锁 与 互斥锁

    • 自旋锁 (spin lock): 如果一个线程需要获取自旋锁,该锁已经被其他线程占用,该线程不会被挂起,而是不断消耗CPU时间,一直试图获取自旋锁。
    • 互斥锁 (mutex):如果一个线程无法获取互斥量,该线程会被直接挂起,不再小号CPU时间,当其他线程释放互斥量后,操作系统会激活被挂起的线程。

    使用场景:

    • 多核处理器:如果预计线程等待锁的时间比较短,短到比线程两次切换上下文的时间还要少的情况下,自旋锁是更好的选择。如果时间比较长,则互斥锁是比较好的选择。
    • 单核处理器:一般不建议使用自旋锁。因为在同一时间片内只有一个线程处在运行状态,如果线程a已经获取到锁,但是此时时间片轮到线程b执行,但是线程b获取锁,只能等待解锁,但是因为自己不挂起,所以线程a无法进入运行状态,只能等到线程b的时间片消耗完,线程a才有机会被OS调度执行。此时使用自旋锁的代价很高。

    如果加锁的代码经常被调用,但是竞争发生的比较少时,应该优先考虑使用自旋锁,毕竟互斥锁的切换上下文的开销比较大。

    性能对比

    iOS中的锁包括:

    • @synchronized
    • NSLock
    • NSCondition
    • NSConditionLock
    • NSRecursiveLock
    • pthread_mutex_t
    • dispatch_semaphore_t
    • OSSpinLock

    做的测试是对每种锁进行100万次的加锁解锁操作,对比时间,使用的iPhone6iOS10.1.1的设备,测试结果如下:

    各种锁的时间性能对比

    从对比可以看出,性能最优的是OSSpinLock ,最差的是@synchronized,下面是我制作的各种锁的性能对比,不同的系统和设备的数值可能会有差异:

    iOS中各种锁的性能对比

    <h3 align = "center">测试代码</h3>

    <a name="fenced-code-block">@synchronized()</a>
    
        CFTimeInterval timeBefore;
        CFTimeInterval timeCurrent;
        NSUInteger i;
        NSUInteger count = 1000*10000;//执行一千万次
    
        //@synchronized
        id obj = [[NSObject alloc]init];;
        timeBefore = CFAbsoluteTimeGetCurrent();
        for(i=0; i<count; i++){
            @synchronized(obj){
            }
        }
        timeCurrent = CFAbsoluteTimeGetCurrent();
        printf("@synchronized  : %f\n", timeCurrent-timeBefore);
    
    <a name="fenced-code-block">NSLock</a>
        NSLock *lock = [[NSLock alloc]init];
        timeBefore = CFAbsoluteTimeGetCurrent();
        for(i=0; i<count; i++){
            [lock lock];
            [lock unlock];
        }
        timeCurrent = CFAbsoluteTimeGetCurrent();
        printf("NSLock  : %f\n", timeCurrent-timeBefore);
    
    <a name="fenced-code-block">NSCondition</a>
        NSCondition *condition = [[NSCondition alloc]init];
        timeBefore = CFAbsoluteTimeGetCurrent();
        for(i=0; i<count; i++){
            [condition lock];
            [condition unlock];
        }
        timeCurrent = CFAbsoluteTimeGetCurrent();
        printf("NSCondition  : %f\n", timeCurrent-timeBefore);
    
    <a name="fenced-code-block">NSConditionLock</a>
        NSConditionLock *conditionLock = [[NSConditionLock alloc]init];
        timeBefore = CFAbsoluteTimeGetCurrent();
        for(i=0; i<count; i++){
            [conditionLock lock];
            [conditionLock unlock];
        }
        timeCurrent = CFAbsoluteTimeGetCurrent();
        printf("NSConditionLock  : %f\n", timeCurrent-timeBefore);
    
    <a name="fenced-code-block">NSRecursiveLock</a>
        NSRecursiveLock *recursiveLock = [[NSRecursiveLock alloc]init];
        timeBefore = CFAbsoluteTimeGetCurrent();
        for(i=0; i<count; i++){
            [recursiveLock lock];
            [recursiveLock unlock];
        }
        timeCurrent = CFAbsoluteTimeGetCurrent();
        printf("NSRecursiveLock  : %f\n", timeCurrent-timeBefore);
    
    <a name="fenced-code-block">pthread_mutex_t</a>
     pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
        timeBefore = CFAbsoluteTimeGetCurrent();
        for(i=0; i<count; i++){
            pthread_mutex_lock(&mutex);
            pthread_mutex_unlock(&mutex);
        }
        timeCurrent = CFAbsoluteTimeGetCurrent();
        printf("pthread_mutex  : %f\n", timeCurrent-timeBefore);
    
    <a name="fenced-code-block">dispatch_semaphore_t</a>
        dispatch_semaphore_t semaphore = dispatch_semaphore_create(1);
        timeBefore = CFAbsoluteTimeGetCurrent();
        for(i=0; i<count; i++){
            dispatch_semaphore_wait(semaphore, DISPATCH_TIME_FOREVER);
            dispatch_semaphore_signal(semaphore);
        }
        timeCurrent = CFAbsoluteTimeGetCurrent();
        printf("dispatch_semaphore  : %f\n", timeCurrent-timeBefore);
    
    <a name="fenced-code-block">OSSpinLock</a>
        OSSpinLock spinlock = OS_SPINLOCK_INIT;
        timeBefore = CFAbsoluteTimeGetCurrent();
        for(i=0; i<count; i++){
            OSSpinLockLock(&spinlock);
            OSSpinLockUnlock(&spinlock);
        }
        timeCurrent = CFAbsoluteTimeGetCurrent();
        printf("OSSpinLock  : %f\n", timeCurrent-timeBefore);
    

    相关文章

      网友评论

        本文标题:iOS中各种锁的性能对比

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