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
@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"];
//初始化NSLock
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.lock unlock];
/***
这里不一样,这里被注释掉了
***/
//一直卖票
[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。