iOS 十种线程锁

锁 是什么意思?ios

  • 咱们在使用多线程的时候多个线程可能会访问同一块资源,这样就很容易引起数据错乱和数据安全等问题,这时候就须要咱们保证每次只有一个线程访问这一块资源,锁 应运而生。安全

  • 这里顺便提一下,上锁的两种方式trylock和lock使用场景:多线程

 

当前线程锁失败,也能够继续其它任务,用 trylock 合适性能

当前线程只有锁成功后,才会作一些有意义的工做,那就 lock,不必轮询 trylock测试

注:如下大部分锁都会提供trylock接口,再也不做解释spa

 

性能图线程

 

<准备操做>对象

 

测试代码blog

#define RHTICK   NSDate *startTime = [NSDate date];递归

#define RHTOCK   NSLog(@"==========Time: %f", -[startTime timeIntervalSinceNow]);

NSUInteger count = 1000*10000;//执行一千万次

RHTICK

for(int i=0; i<count; i++) {

加锁

解锁

}

RHTOCK

注:测试中执行时间会波动,因此我取的平均值.

 

1、OSSpinLock (自旋锁)

 

测试中效率最高的锁, 不过经YYKit做者确认, OSSpinLock已经再也不线程安全,OSSpinLock有潜在的优先级反转问题.再也不安全的 OSSpinLock;

 

  • 0.097348s

 

须要导入头文件

#import <libkern/OSAtomic.h>

// 初始化

 OSSpinLock spinLock = OS_SPINLOCK_INIT;

// 加锁

OSSpinLockLock(&spinLock);

// 解锁

OSSpinLockUnlock(&spinLock);

// 尝试加锁,能够加锁则当即加锁并返回 YES,反之返回 NO

OSSpinLockTry(&spinLock)

/*

注:苹果爸爸已经在iOS10.0之后废弃了这种锁机制,使用os_unfair_lock 替换,

顾名思义可以保证不一样优先级的线程申请锁的时候不会发生优先级反转问题.

*/

 

2、os_unfair_lock(自旋锁)

 

  • 0.171789s

 

须要导入头文件

#import <os/lock.h>

// 初始化

 os_unfair_lock unfair_lock = OS_UNFAIR_LOCK_INIT;

// 加锁

os_unfair_lock_lock(&unfair_lock);

// 解锁

os_unfair_lock_unlock(&unfair_lock);

// 尝试加锁,能够加锁则当即加锁并返回 YES,反之返回 NO

os_unfair_lock_trylock(&unfair_lock);

/*

注:解决不一样优先级的线程申请锁的时候不会发生优先级反转问题.

不过相对于 OSSpinLock , os_unfair_lock性能方面减弱了许多.

*/

 

3、dispatch_semaphore (信号量)

 

  • 0.155043s

 

// 初始化

dispatch_semaphore_t semaphore_t = dispatch_semaphore_create(1);

// 加锁

dispatch_semaphore_wait(semaphore_t,DISPATCH_TIME_FOREVER);

// 解锁

dispatch_semaphore_signal(semaphore_t);

/*

注: dispatch_semaphore  其余两个功能

1.还能够起到阻塞线程的做用.

2.能够实现定时器功能,这里不作过多介绍.

*/

 

4、pthread_mutex(互斥锁)

 

  • 0.262592s

 

须要导入头文件

#import <pthread/pthread.h>

// 初始化(两种)

1.普通初始化

pthread_mutex_t mutex_t;

pthread_mutex_init(&mutex_t, NULL); 

2.宏初始化

pthread_mutex_t mutex =PTHREAD_MUTEX_INITIALIZER;

// 加锁

pthread_mutex_lock(&mutex_t);

// 解锁

pthread_mutex_unlock(&mutex_t);

// 尝试加锁,能够加锁时返回的是 0,不然返回一个错误

pthread_mutex_trylock(& mutex_t)

 

5、NSLock(互斥锁、对象锁)

 

  • 0.283196s

 

// 初始化

NSLock *_lock = [[NSLock alloc]init];

// 加锁

[_lock lock];

// 解锁

[_lock unlock];

// 尝试加锁,能够加锁则当即加锁并返回 YES,反之返回 NO

[_lock tryLock];

 

6、NSCondition(条件锁、对象锁)

 

  • 0.293046s

 

// 初始化

NSCondition *_condition= [[NSCondition alloc]init];

// 加锁

[_condition lock];

// 解锁

[_condition unlock];

/*

其余功能接口

wait 进入等待状态

waitUntilDate:让一个线程等待必定的时间

signal 唤醒一个等待的线程

broadcast 唤醒全部等待的线程

注: 所测时间波动太大, 有时候会快于 NSLock, 我取得中间值.

*/

 

7、NSConditionLock(条件锁、对象锁)

 

  • 0.950285s

 

// 初始化

NSConditionLock *_conditionLock = [[NSConditionLock alloc]init];

// 加锁

[_conditionLock lock];

// 解锁

[_conditionLock unlock];

// 尝试加锁,能够加锁则当即加锁并返回 YES,反之返回 NO

[_conditionLock tryLock];

/*

其余功能接口

- (instancetype)initWithCondition:(NSInteger)condition NS_DESIGNATED_INITIALIZER; //初始化传入条件

- (void)lockWhenCondition:(NSInteger)condition;//条件成立触发锁

- (BOOL)tryLockWhenCondition:(NSInteger)condition;//尝试条件成立触发锁

- (void)unlockWithCondition:(NSInteger)condition;//条件成立解锁

- (BOOL)lockBeforeDate:(NSDate *)limit;//触发锁 在等待时间以内

- (BOOL)lockWhenCondition:(NSInteger)condition beforeDate:(NSDate *)limit;//触发锁 条件成立 而且在等待时间以内

*/

 

8、NSRecursiveLock(递归锁、对象锁)

 

  • 0.473536s

 

// 初始化

NSRecursiveLock *_recursiveLock = [[NSRecursiveLock alloc]init];

// 加锁

[_recursiveLock lock];

// 解锁

[_recursiveLock unlock];

// 尝试加锁,能够加锁则当即加锁并返回 YES,反之返回 NO

[_recursiveLock tryLock];

/*

注: 递归锁能够被同一线程屡次请求,而不会引发死锁。

即在同一线程中在未解锁以前还能够上锁, 执行锁中的代码。

这主要是用在循环或递归操做中。

- (BOOL)lockBeforeDate:(NSDate *)limit;//触发锁 在等待时间以内

*/

 

9、@synchronized(条件锁)

 

  • 1.101924s

 

// 初始化

@synchronized(条件){

}

     更多关于@synchronized;

 

10、pthread_mutex(recursive)(递归锁)

 

  • 0.372398s

 

// 初始化

pthread_mutex_t mutex_t;

pthread_mutexattr_t attr;

pthread_mutexattr_init(&attr); //初始化attr而且给它赋予默认pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE); //设置锁类型,这边是设置为递归锁

pthread_mutex_init(&mutex_t, &attr);

pthread_mutexattr_destroy(&attr); //销毁一个属性对象,在从新进行初始化以前该结构不能从新使用

// 加锁

pthread_mutex_lock(&mutex_t);

// 解锁

pthread_mutex_unlock(&mutex_t);

/*

注: 递归锁能够被同一线程屡次请求,而不会引发死锁。

即在同一线程中在未解锁以前还能够上锁, 执行锁中的代码。

这主要是用在循环或递归操做中。

*/

 

性能总结

 

OSSpinLock                          0.097348s

dispatch_semaphore                  0.155043s

os_unfair_lock                      0.171789s

pthread_mutex                       0.262592s

NSLock                               0.283196s

pthread_mutex(recursive)            0.372398s

NSRecursiveLock                     0.473536s

NSConditionLock                     0.950285s

@synchronized                       1.101924s

 

注:建议正常锁功能用 pthread_mutex ,os_unfair_lock (适配低版本)

相关文章
相关标签/搜索