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鎖也算有了一定的了解。 還是那句話,如您發現任何錯誤,歡迎留言指正~
總結
- 上一篇: rhel 7.2 mysql_Rhel7
- 下一篇: 当IE浏览器设置了代理,改变不了的时候,