本文由 简悦 SimpRead 转码,
原文地址 www.jianshu.com
NSRecursiveLock
下面是苹果官方文档的说法:
A lock that may be acquired multiple times by the same thread without causing a deadlock.
Overview
NSRecursiveLock defines a lock that may be acquired multiple times by the same thread without causing a deadlock, a situation where a thread is permanently blocked waiting for itself to relinquish a lock. While the locking thread has one or more locks, all other threads are prevented from accessing the code protected by the lock.
下面是个人的理解以及一些例子
#import <Foundation/Foundation.h>
@interface NSLockTest : NSObject
- (void)forTest;
@end
#import "NSLockTest.h"
@interface NSLockTest()
@property (nonatomic,strong) NSArray *tickets;
@property (nonatomic,assign) int soldCount;
@property (nonatomic,strong) NSRecursiveLock *lock;
@end
@implementation NSLockTest
- (void)forTest
{
self.tickets = @[@"南京-北京A101",@"南京-北京A102",@"南京-北京A103",@"南京-北京A104",@"南京-北京A105",@"南京-北京A106",@"南京-北京A107",@"南京-北京A108",@"南京-北京A109",@"南京-北京A110",@"南京-北京A111",@"南京-北京A112",@"南京-北京A113",@"南京-北京A114",@"南京-北京A115",@"南京-北京A116",@"南京-北京A117",@"南京-北京A118",@"南京-北京A119",@"南京-北京A120",@"南京-北京A121",@"南京-北京A122",@"南京-北京A123",@"南京-北京A124",@"南京-北京A125",@"南京-北京A126",@"南京-北京A127",@"南京-北京A128",@"南京-北京A129",@"南京-北京A130"];
self.lock = [[NSRecursiveLock alloc] init];
NSThread *windowOne = [[NSThread alloc] initWithTarget:self selector:@selector(soldTicket) object:nil];
windowOne.name = @"一号窗口";
[windowOne start];
NSThread *windowTwo = [[NSThread alloc] initWithTarget:self selector:@selector(soldTicket) object:nil];
windowTwo.name = @"二号窗口";
[windowTwo start];
}
-(void)soldTicket
{
[self.lock lock];
if (self.soldCount == self.tickets.count) {
NSLog(@"=====%@ 剩余票数:%lu",[[NSThread currentThread] name],self.tickets.count-self.soldCount);
[self.lock unlock];
return;
}
[NSThread sleepForTimeInterval:0.2];
self.soldCount++;
NSLog(@"=====%@ %@ 剩%lu",[[NSThread currentThread] name],self.tickets[self.soldCount-1],self.tickets.count-self.soldCount);
[self.lock unlock];
[self soldTicket];
}
@end
这种写法其实跟上一篇 NSLock 一模一样,这样是没问题的,我要说的是 NSLock 和 NSRecursiveLock 的却别
之前讲过,如果 NSLock lock 了之后,没有 unlock 那么会发生死锁。
那么 NSRecursiveLock lock 之后,没有 unlock,会发生什么呢?
[NSThread sleepForTimeInterval:0.2];
self.soldCount++;
NSLog(@"=====%@ %@ 剩%lu",[[NSThread currentThread] name],self.tickets[self.soldCount-1],self.tickets.count-self.soldCount);
[self soldTicket];
NSRecursiveLock 是递归锁,在同一个线程中重复加锁不会导致死锁。但是还是会干扰到其他线程的。
从运行的结果上看,NSThread *windowOne,NSThread *windowTwo 只有一个线程在跑着。没有 unlock 虽然没有影响当前线程,但是其他线程还是会被阻塞。
一号窗口 南京-北京A101 剩29
一号窗口 南京-北京A101 剩28
一号窗口 南京-北京A101 剩27
.
.
.
一号窗口 南京-北京A101 剩0
一号窗口 剩余票数:0
正常情况下,每个售票窗口都应该在卖票的。
注意点
1、NSLock 如果没有在 lock 之后 unlock,那么会被死锁
2、NSRecursiveLock,在这一点优化了不少,在单一线程中,重复 lock 也不会影响该线程。但是没有及时 unlock,是会导致其他线程阻塞的。
3、还是得记得 unlock。