iOS锁-NSRecursiveLock

作者: 口子窖 | 来源:发表于2018-07-11 15:57 被阅读1次

    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"];
        //初始化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

        本文链接:https://www.haomeiwen.com/subject/nxafpftx.html