OSSpinLock
OSSpinLock 自旋锁,不会让等待的线程进入睡眠状态,效率高。
OSSpinLock 不能保证安全。系统维护了5个不同的线程优先级/QoS: background,utility,default,user-initiated,user-interactive。高优先级线程始终会在低优先级线程前执行,一个线程不会受到比它更低优先级线程的干扰。这种线程调度算法会差生潜在的优先级反转问题,从而破坏spin Lock
优先级反转:如果一个低优先级的线程获得锁并访问共享资源,这时一个高优先级的线程也尝试获得该锁,它会处于spin lock 的忙等状态从而占用大量CPU。此时低优先级线程无法与高优先级线程争夺CPU时间,从而导致任务迟迟完不成、无法释放Lock。
最终的结论就是,除非开发者能保证访问锁的线程全部都处于同一优先级,否则 iOS 系统中所有类型的自旋锁都不能再使用了
OS_SPINLOCK_INIT:默认值为0,在locked状态时,就会大于0,unlocked 状态下为 0
OSSpinLockLock(&oslock):上锁,参数为OSSpinLock 地址
OSSpinLockUnlock(&oslock):解锁,参数为OSSpinLock 地址
OSSpinLockTry(&oslock):尝试加锁,可以加锁则立即加锁,并返回YES,反之返回NO。
dispatch_semaphore 信号量
dispatch_semaphore_create(1) 传值必须 >=0 ,若传为0,则阻塞线程并等待
dispatch_semaphore_wait(signal, overTime): 可以理解为lock,会使得signal值 -1
dispatch_semaphore_signal(signal): 可以理解为unlock, 会使得signal值 +1
phread_mutex
static pthread_mutex_t pLock;
pthread_mutex_init(&pLock, NULL);
pthread_mutex_lock(&pLock);
pthread_mutex_unlock(&pLock);
#pthread_mutex 中也有个pthread_mutex_trylock(&pLock), 和上面提到的OSSpinLockTry(&oslock)区别在于,前者可以加锁时返回的是0,否则返回一个错误提示码;后者返回的YES 和 NO
pthread_mutex(recursive)递归锁
加锁后只能有一个线程访问该对象,后面的线程需要排队,并且 lock 和 unlock 是对应出现的,同一线程多次 lock 是不允许的,而递归锁允许同一个线程在未释放其拥有的锁时反复对该锁进行加锁操作
static pthread_mutex_t pLock;
pthread_mutexattr_t attr;
pthread_mutexattr_init(&attr); //初始化attr并且给它赋予默认
pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE); //设置锁类型,这边是设置为递归锁
pthread_mutex_init(&pLock, &attr);
pthread_mutexattr_destroy(&attr); //销毁一个属性对象,在重新进行初始化之前该结构不能重新使用
pthread_mutex_lock(&pLock);
pthread_mutex_unlock(&pLock);
NSLock
lock 、unlock 、tryLock 能加锁返回YES并执行加锁操作,相当于lock,反之返回NO
NSLock *lock = [NSLock new];
[lock lock]
[lock unlock]
NSCondition
wait:进入等待状态
waitUntilDate:让一个线程等待一定的时间
signal: 唤醒一个等待的线程
broadcast: 唤醒所有等待的线程
// 等待2秒
NSCondition *cLock = [NSCondition new];
//线程1
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
NSLog(@"start");
[cLock lock];
[cLock waitUntilDate:[NSDate dateWithTimeIntervalSinceNow:2]];
NSLog(@"线程1");
[cLock unlock];
});
// 唤醒一个等待线程
NSCondition *cLock = [NSCondition new];
//线程1
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
[cLock lock];
NSLog(@"线程1加锁成功");
[cLock wait];
NSLog(@"线程1");
[cLock unlock];
});
//线程2
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
[cLock lock];
NSLog(@"线程2加锁成功");
[cLock wait];
NSLog(@"线程2");
[cLock unlock];
});
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
sleep(2);
NSLog(@"唤醒一个等待的线程");
[cLock signal];
});
// 唤醒所有等待的线程
.........
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
sleep(2);
NSLog(@"唤醒所有等待的线程");
[cLock broadcast];
});
NSRecursiveLock 递归锁
NSRecursiveLock *rLock = [NSRecursiveLock new];
[rLock lock];
[rLock unlock];
@synchronized
//线程1
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
@synchronized (self) {
sleep(2);
NSLog(@"线程1");
}
});
//线程2
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
@synchronized (self) {
NSLog(@"线程2");
}
});
NSConditionLock 条件锁
NSConditionLock *cLock = [[NSConditionLock alloc] initWithCondition:0];
//线程1
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
if([cLock tryLockWhenCondition:0]){
NSLog(@"线程1");
[cLock unlockWithCondition:1];
}else{
NSLog(@"失败");
}
});
//线程2
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
[cLock lockWhenCondition:3];
NSLog(@"线程2");
[cLock unlockWithCondition:2];
});
//线程3
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
[cLock lockWhenCondition:1];
NSLog(@"线程3");
[cLock unlockWithCondition:3];
});
参考:
ios 中会使用到的锁
网友评论