本文主要是介绍互斥锁--NSLock,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!
互斥锁–NSLock
互斥锁主要用于对临界区资源的保护,在多线程编程中防止不同的线程对同一公共资源操作(读或写),当A线程的任务没有执行完毕时(资源被锁住),B线程会进入睡眠状态等待A线程的任务执行完毕,当A程的任务执行完毕,B线程会自动唤醒然后执行任务。iOS中常用的互斥锁有NSLock、@synchronized、pthread_mutex、NSCondition、NSConditionLock、NSRecursiveLock。下面我们逐一介绍这几个锁,现在我们先看一下NSLock的相关内容。
1、NSLock
**介绍:**在Fondation库中提供的基本的锁,NSLock继承自NSObject,遵守NSLocking协议,A线程获取锁后,B线程在获取锁时会被系统挂起,知道A线程释放锁,B线程才可以获取锁。它以对象的形式供开发者使用,我们先看一下它的API:
@protocol NSLocking- (void)lock;
- (void)unlock;@end@interface NSLock : NSObject <NSLocking> {
@privatevoid *_priv;
}- (BOOL)tryLock;
- (BOOL)lockBeforeDate:(NSDate *)limit;@property (nullable, copy) NSString *name;
@end
**注意:**要成对使用NSLock,不要连续锁定,否则会造成死锁,下面的例子就是连续锁定导致死锁。
-(void)methodA
{self.lock = [[NSLock alloc]init];[self.lock lock];//1NSLog(@"1");[self methodB];//2NSLog(@"2");[self.lock unlock];
}-(void)test
{[self.lock lock];NSLog(@"3");[self.lock unlock];
}
最后打印出1,代码已经死锁,因为当前线程运行到1时获取锁并加锁,运行到2时在test方法中再次获取锁加锁,但是test方法中的锁和1中的锁是同样的锁,需等待当前线程解锁,但是当前线程正在执行test方法,test方法等待当前线程释放锁,造成死锁。
解决办法:NSLock是非递归锁,当同一线程重复获取同一非递归锁时,就会发生死锁,可以用递归锁代替NSLock,比如NSRecursiveLock或者@synchronized
2、实现
NSLock锁是对pthread_mutex的简单封装,NSLock的底层实现,是创建一个PTHREAD_MUTEXT_ERRORCHECK类型的pthread_mutex,由于封装时增加了错误核查和提示,会损失一定的性能。从GNUSetup里面的实现我们即可看出NSLock是对pthread_mutex的封装。
-
-init方法使用pthread_mutex_init来初始化一个锁。
-
-lockBeforeDate:方法是一个循环,在时间没有结束前使用pthread_mutex_trylock去检查是否可以获取锁,获取成功返回yes,表示线程可以操作某个资源,如果获取失败提示出错,并且让出资源,让优先级高的线程先获取资源。
/* Use an error-checking lock. This is marginally slower, but lets us throw* exceptions when incorrect locking occurs.*/
- (id) init
{if (nil != (self = [super init])){if (0 != pthread_mutex_init(&_mutex, &attr_reporting)){DESTROY(self);}}return self;
}- (BOOL) lockBeforeDate: (NSDate*)limit
{do{int err = pthread_mutex_trylock(&_mutex);if (0 == err){CHK(Hold)return YES;}if (EDEADLK == err){(*_NSLock_error_handler)(self, _cmd, NO, @"deadlock");}sched_yield();} while ([limit timeIntervalSinceNow] > 0);return NO;
}
这篇关于互斥锁--NSLock的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!