iOS锁-NSRecursiveLock

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。

你可能感兴趣的:(iOS锁-NSRecursiveLock)