在高并行的代码环境中,我们常常会碰到这样的情况:多个线程同时访问某一段代码,产生资源竞争,导致程序异常。线程锁可以帮我们解决这样的问题,它可以让这些并行的线程同步地访问这段代码,让我们的程序正常执行。通过解决下面这个问题(参见 http://www.jianshu.com/p/b3bd070cd372 ),介绍几种常用线程锁的用法。
- (void)testDispatchSemaphore
{
dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
NSMutableArray *mutableArray = [NSMutableArray array];
for (int i = 0; i < 100000; ++i) {
dispatch_async(queue, ^{
[mutableArray addObject:[NSNumber numberWithInt:i]];
});
}
}
一、NSLock
NSLock *lock = [[NSLock alloc] init];
for (int i = 0; i < 100000; ++i) {
dispatch_async(queue, ^{
//加锁
[lock lock];
//需要加锁的代码
[mutableArray addObject:[NSNumber numberWithInt:i]];
//解锁
[lock unlock];
});
}
三步:
- 初始化锁:
NSLock *lock = [[NSLock alloc] init];
- 对代码加锁:
[lock lock];
- 对代码解锁:
[lock unlock];
二、pthread_mutex
static pthread_mutex_t pLock;
pthread_mutex_init(&pLock, NULL);
for (int i = 0; i < 100000; ++i) {
dispatch_async(queue, ^{
//加锁
pthread_mutex_lock(&pLock);
//需要加锁的代码
[mutableArray addObject:[NSNumber numberWithInt:i]];
//解锁
pthread_mutex_unlock(&pLock);
});
}
四步:
- 声明:
static pthread_mutex_t pLock;
这里需要声明为静态变量,不然参数类型不匹配。
- 初始化:
pthread_mutex_init(&pLock, NULL);
- 加锁
pthread_mutex_lock(&pLock);
- 解锁
pthread_mutex_unlock(&pLock);
三、@synchronized
for (int i = 0; i < 100000; ++i) {
dispatch_async(queue, ^{
@synchronized (self) {
[mutableArray addObject:[NSNumber numberWithInt:i]];
}
});
}
最简单,但是性能最差
四、Dispatch Semaphore
我写的另一篇文章有分析到,详情见http://www.jianshu.com/p/b3bd070cd372
综合性能和可读性,我比较喜欢NSLock,对性能要求较高的童鞋可以使用pthread_mutex_t和Semaphore。自旋锁OSSpinLock被苹果工程师证实不安全,苹果使用pthread_mutex_t进行了替代,谷歌使用Semaphore。