iOS多线程——锁

iOS多线程——锁

在开发中,多线程编程是必不可少的,多线程的线程安全也是要考虑的,可能最有印象的应该还是atomic属性吧,其次就是GCD的dispatch_semaphore。于是就总结了一下,iOS开发中的线程安全措施。大致有如下几种:

  • atomic属性
  • @synchronize(对象)
  • NSLock 需要提一下,lock、unlock方法必须在一个线程调用,这里说的很清楚
  • NSRecursiveLock 递归锁,能在同一个线程多次请求不会死锁
  • NSCondition
  • NSConditionLock
  • OSSpinLock 自旋锁,被弃用了,因为存在优先级反转问题,苹果已经弃用,并用os_unfair_lock作为替代。需要引入头文件 #impot< libkern/OSAtomic.h>
  • os_unfair_lock 不公平的锁,就是解决优先级反转问题。 需要引入头文件 #import < os/lock.h>

  • pthread_mutex 创建需由pthread_attr_t参数,如果参数attr为空,则使用默认的互斥锁属性,默认属性为快速互斥锁 。互斥锁的属性在创建锁的时候指定,不同的锁类型在试图对一个已经被锁定的互斥锁加锁时表现不同。(#define PTHREAD_MUTEX_NORMAL
    #define PTHREAD_MUTEX_ERRORCHECK
    #define PTHREAD_MUTEX_RECURSIVE 三种属性)至于不同属性的性能,都是一家的,在这里就不比较了

  • dispatch_semaphore

既然有这么多的实现方式,当然要一较高下,选择自己喜欢的方式,于是写了下面的测试代码比较性能:

NSMutableArray *timeArr = [NSMutableArray array];
    CFTimeInterval start,end,cost;
    NSInteger count = 100000;
    NSArray *nameArr = @[@"OSSpinLock",@"NSLock",@"dispatch_semaphore",@"pthread_mutex",@"NSCondition",@"NSConditionLock",@"NSRecursiveLock",@"@synchronized",@"os_unfair_lock"];

#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wdeprecated"
    {
        OSSpinLock lock = OS_SPINLOCK_INIT;
        start = CFAbsoluteTimeGetCurrent();
        for (int i = 0; i < count; i++) {
            OSSpinLockLock(&lock);
            OSSpinLockUnlock(&lock);
        }
        end = CFAbsoluteTimeGetCurrent();
        cost = end - start;
        [timeArr addObject:@(cost)];
    }
#pragma clang pop


    {
        NSLock *lock = [NSLock new];
        start = CFAbsoluteTimeGetCurrent();
        for (int i = 0; i < count; i++) {
            [lock lock];
            [lock unlock];
        }
        end = CFAbsoluteTimeGetCurrent();
        cost = end - start;
        [timeArr addObject:@(cost)];
    }



    {
        dispatch_semaphore_t lock =  dispatch_semaphore_create(1);
        start = CFAbsoluteTimeGetCurrent();
        for (int i = 0; i < count; i++) {
            dispatch_semaphore_wait(lock, DISPATCH_TIME_FOREVER);
            dispatch_semaphore_signal(lock);
        }
        end = CFAbsoluteTimeGetCurrent();
        cost = end - start;
        [timeArr addObject:@(cost)];
    }


    {
        pthread_mutex_t lock;
        pthread_mutex_init(&lock, NULL);
        start = CFAbsoluteTimeGetCurrent();
        for (int i = 0; i < count; i++) {
            pthread_mutex_lock(&lock);
            pthread_mutex_unlock(&lock);
        }
        end = CFAbsoluteTimeGetCurrent();
        cost = end - start;
        [timeArr addObject:@(cost)];
    }

    {
        NSCondition *lock = [NSCondition new];
        start = CFAbsoluteTimeGetCurrent();
        for (int i = 0; i < count; i++) {
            [lock lock];
            [lock unlock];
        }
        end = CFAbsoluteTimeGetCurrent();
        cost = end - start;
        [timeArr addObject:@(cost)];
    }

    {
        NSConditionLock *lock = [[NSConditionLock alloc] initWithCondition:1];
        start = CFAbsoluteTimeGetCurrent();
        for (int i = 0; i < count; i++) {
            [lock lock];
            [lock unlock];
        }
        end = CFAbsoluteTimeGetCurrent();
        cost = end - start;
        [timeArr addObject:@(cost)];
    }

    {
        NSRecursiveLock *lock = [NSRecursiveLock new];
        start = CFAbsoluteTimeGetCurrent();
        for (int i = 0; i < count; i++) {
            [lock lock];
            [lock unlock];
        }
        end = CFAbsoluteTimeGetCurrent();
        cost = end - start;
        [timeArr addObject:@(cost)];
    }

    {
        NSObject *lock = [NSObject new];
        start = CFAbsoluteTimeGetCurrent();
        for (int i = 0; i < count; i++) {
            @synchronized(lock) {}
        }
        end = CFAbsoluteTimeGetCurrent();
        cost = end - start;
        [timeArr addObject:@(cost)];
    }

    {
        os_unfair_lock_t unfairLock;
        unfairLock = &(OS_UNFAIR_LOCK_INIT);
        start = CFAbsoluteTimeGetCurrent();
        for (int i = 0; i < count; i++) {
            os_unfair_lock_lock(unfairLock);
            os_unfair_lock_unlock(unfairLock);
        }
        end = CFAbsoluteTimeGetCurrent();
        cost = end - start;
        [timeArr addObject:@(cost)];
    }

    for (int i = 0; i < timeArr.count; i++) {
        NSLog(@"------%@------%@\n",timeArr[i],nameArr[i]);
    }

最后打印结果如下:

 ------0.0009900331497192383------OSSpinLock
 ------0.00348198413848877------NSLock
 ------0.001325011253356934------dispatch_semaphore
 ------0.002358973026275635------pthread_mutex
 ------0.003148019313812256------NSCondition
 ------0.01061898469924927------NSConditionLock
 ------0.00425797700881958------NSRecursiveLock
 ------0.0124550461769104------@synchronized
 ------0.00145798921585083------os_unfair_lock

可以看出要是没有优先级反转的问题的话,osspinlock占有绝对,其次就是dispatch_semaphore,dispatch_semaphore和os_unfair_lock差距很小,其次就是pthread_mutex。其实在测试的时候呢,性能和次数是有关系的,即是说这几种锁在不同的情形下会发挥最好性能,次数量大的时候呢,性能排名就如上面一样。所以在项目中使用的话,就根据项目情况选择即可。


好吧!就到这里,对iOS锁也算有了一定的了解。 还是那句话,如您发现任何错误,欢迎留言指正~

你可能感兴趣的:(iOS开发)