IOS高级开发之多线程(五)NSOperation 2

接着看NSOperation、NSOperationQueue线程间的通信:

应用场景:比如我们经常把一些耗时的操作比如下载图片放在子线程,那么当这个完成之后,我们就需要回到主线程,这个时候就需要用到线程间的通信。

来看下代码:

//线程间通信
-(void)communication{
    //1.创建队列
    NSOperationQueue *queue = [[NSOperationQueue alloc] init];
    
    //2.添加操作
    [queue addOperationWithBlock:^{
        //异步进行的耗时操作
        for (int i=0; i<2; ++i) {
            [NSThread sleepForTimeInterval:2.0];//模拟耗时操作
            NSLog(@"1----%@",[NSThread currentThread]);//打印当前线程
        }
        
        //回到主线程
        [[NSOperationQueue mainQueue] addOperationWithBlock:^{
            //进行UI刷新操作
            for (int i=0; i<2; ++i) {
                [NSThread sleepForTimeInterval:2.0];
                NSLog(@"2----%@",[NSThread currentThread]);
            }
        }];
    }];
}

  来看打印:

2019-04-09 11:25:34.507056+0800 MyNSOperation[2488:37353] 1----<NSThread: 0x600000082840>{number = 3, name = (null)}
2019-04-09 11:25:36.510730+0800 MyNSOperation[2488:37353] 1----<NSThread: 0x600000082840>{number = 3, name = (null)}
2019-04-09 11:25:38.513231+0800 MyNSOperation[2488:37047] 2----<NSThread: 0x6000000e29c0>{number = 1, name = main}
2019-04-09 11:25:40.516515+0800 MyNSOperation[2488:37047] 2----<NSThread: 0x6000000e29c0>{number = 1, name = main}

  可以看到,在子线程进行异步操作后,回到了主线程。

再来看下NSOperation与NSOperationQueue的线程同步与线程安全

我们来看一个经典的卖火车票的例子,假如我们不考虑线程安全是啥情况。

/*
 非线程安全,不用锁
 
 */
-(void)initTicketStatusNotSafe{
    NSLog(@"currentThread---%@",[NSThread currentThread]);
    self.ticketCount = 50;
    //1.创建queue1,queue1代表北京售票窗口
    NSOperationQueue *queue1 = [[NSOperationQueue alloc] init];
    queue1.maxConcurrentOperationCount = 1;
    //2.创建queue2.queue2代表上海售票窗口
    NSOperationQueue *queue2 = [[NSOperationQueue alloc] init];
    queue2.maxConcurrentOperationCount = 1;
    //3.创建卖票的操作
    NSBlockOperation *op1 = [NSBlockOperation blockOperationWithBlock:^{
        [self saleTicketNotSafe];
    }];
    //4.创建卖票操作
    NSBlockOperation *op2 = [NSBlockOperation blockOperationWithBlock:^{
        [self saleTicketNotSafe];
    }];
    
    //5.开始卖票
    [queue1 addOperation:op1];
    [queue2 addOperation:op2];
}

//售卖火车票
-(void)saleTicketNotSafe{
    while(true){
        if (self.ticketCount>0) {
            //如果还有票,就继续卖
            self.ticketCount--;
            NSLog(@"%@",[NSString stringWithFormat:@"剩余票数:%d 窗口%@",self.ticketCount,[NSThread currentThread]]);
            [NSThread sleepForTimeInterval:2.0];
        }else{
            NSLog(@"所有的火车票已售完");
            break;
        }
    }
}

  看打印情况:

2019-04-09 11:57:13.000691+0800 MyNSOperation[3785:58834] currentThread---<NSThread: 0x600002ad1240>{number = 1, name = main}
2019-04-09 11:57:13.006247+0800 MyNSOperation[3785:58934] 剩余票数:49 窗口<NSThread: 0x600002a87c00>{number = 3, name = (null)}
2019-04-09 11:57:13.006501+0800 MyNSOperation[3785:58932] 剩余票数:48 窗口<NSThread: 0x600002ab8040>{number = 4, name = (null)}
2019-04-09 11:57:15.011866+0800 MyNSOperation[3785:58934] 剩余票数:47 窗口<NSThread: 0x600002a87c00>{number = 3, name = (null)}
2019-04-09 11:57:15.011959+0800 MyNSOperation[3785:58932] 剩余票数:46 窗口<NSThread: 0x600002ab8040>{number = 4, name = (null)}
2019-04-09 11:57:17.015980+0800 MyNSOperation[3785:58934] 剩余票数:45 窗口<NSThread: 0x600002a87c00>{number = 3, name = (null)}
2019-04-09 11:57:17.015980+0800 MyNSOperation[3785:58932] 剩余票数:45 窗口<NSThread: 0x600002ab8040>{number = 4, name = (null)}
2019-04-09 11:57:19.020346+0800 MyNSOperation[3785:58934] 剩余票数:43 窗口<NSThread: 0x600002a87c00>{number = 3, name = (null)}
2019-04-09 11:57:19.020354+0800 MyNSOperation[3785:58932] 剩余票数:44 窗口<NSThread: 0x600002ab8040>{number = 4, name = (null)}
2019-04-09 11:57:21.026026+0800 MyNSOperation[3785:58934] 剩余票数:42 窗口<NSThread: 0x600002a87c00>{number = 3, name = (null)}
2019-04-09 11:57:21.026112+0800 MyNSOperation[3785:58932] 剩余票数:41 窗口<NSThread: 0x600002ab8040>{number = 4, name = (null)}
2019-04-09 11:57:23.026638+0800 MyNSOperation[3785:58934] 剩余票数:39 窗口<NSThread: 0x600002a87c00>{number = 3, name = (null)}
2019-04-09 11:57:23.026648+0800 MyNSOperation[3785:58932] 剩余票数:40 窗口<NSThread: 0x600002ab8040>{number = 4, name = (null)}
2019-04-09 11:57:25.031698+0800 MyNSOperation[3785:58934] 剩余票数:38 窗口<NSThread: 0x600002a87c00>{number = 3, name = (null)}
2019-04-09 11:57:25.031763+0800 MyNSOperation[3785:58932] 剩余票数:37 窗口<NSThread: 0x600002ab8040>{number = 4, name = (null)}
2019-04-09 11:57:27.032664+0800 MyNSOperation[3785:58934] 剩余票数:36 窗口<NSThread: 0x600002a87c00>{number = 3, name = (null)}
2019-04-09 11:57:27.032664+0800 MyNSOperation[3785:58932] 剩余票数:35 窗口<NSThread: 0x600002ab8040>{number = 4, name = (null)}
2019-04-09 11:57:29.036969+0800 MyNSOperation[3785:58934] 剩余票数:34 窗口<NSThread: 0x600002a87c00>{number = 3, name = (null)}
2019-04-09 11:57:29.037052+0800 MyNSOperation[3785:58932] 剩余票数:33 窗口<NSThread: 0x600002ab8040>{number = 4, name = (null)}
2019-04-09 11:57:31.041413+0800 MyNSOperation[3785:58934] 剩余票数:31 窗口<NSThread: 0x600002a87c00>{number = 3, name = (null)}
2019-04-09 11:57:31.041416+0800 MyNSOperation[3785:58932] 剩余票数:32 窗口<NSThread: 0x600002ab8040>{number = 4, name = (null)}
2019-04-09 11:57:33.044314+0800 MyNSOperation[3785:58934] 剩余票数:30 窗口<NSThread: 0x600002a87c00>{number = 3, name = (null)}
2019-04-09 11:57:33.044314+0800 MyNSOperation[3785:58932] 剩余票数:29 窗口<NSThread: 0x600002ab8040>{number = 4, name = (null)}
2019-04-09 11:57:35.049399+0800 MyNSOperation[3785:58934] 剩余票数:28 窗口<NSThread: 0x600002a87c00>{number = 3, name = (null)}
2019-04-09 11:57:35.049449+0800 MyNSOperation[3785:58932] 剩余票数:28 窗口<NSThread: 0x600002ab8040>{number = 4, name = (null)}
2019-04-09 11:57:37.054456+0800 MyNSOperation[3785:58934] 剩余票数:27 窗口<NSThread: 0x600002a87c00>{number = 3, name = (null)}
2019-04-09 11:57:37.054456+0800 MyNSOperation[3785:58932] 剩余票数:27 窗口<NSThread: 0x600002ab8040>{number = 4, name = (null)}
2019-04-09 11:57:39.057780+0800 MyNSOperation[3785:58934] 剩余票数:26 窗口<NSThread: 0x600002a87c00>{number = 3, name = (null)}
2019-04-09 11:57:39.057780+0800 MyNSOperation[3785:58932] 剩余票数:26 窗口<NSThread: 0x600002ab8040>{number = 4, name = (null)}
2019-04-09 11:57:41.058922+0800 MyNSOperation[3785:58932] 剩余票数:25 窗口<NSThread: 0x600002ab8040>{number = 4, name = (null)}
2019-04-09 11:57:41.058922+0800 MyNSOperation[3785:58934] 剩余票数:25 窗口<NSThread: 0x600002a87c00>{number = 3, name = (null)}
2019-04-09 11:57:43.062224+0800 MyNSOperation[3785:58932] 剩余票数:24 窗口<NSThread: 0x600002ab8040>{number = 4, name = (null)}
2019-04-09 11:57:43.062312+0800 MyNSOperation[3785:58934] 剩余票数:23 窗口<NSThread: 0x600002a87c00>{number = 3, name = (null)}
2019-04-09 11:57:45.066320+0800 MyNSOperation[3785:58934] 剩余票数:21 窗口<NSThread: 0x600002a87c00>{number = 3, name = (null)}
2019-04-09 11:57:45.066320+0800 MyNSOperation[3785:58932] 剩余票数:22 窗口<NSThread: 0x600002ab8040>{number = 4, name = (null)}
2019-04-09 11:57:47.070458+0800 MyNSOperation[3785:58934] 剩余票数:20 窗口<NSThread: 0x600002a87c00>{number = 3, name = (null)}
2019-04-09 11:57:47.070470+0800 MyNSOperation[3785:58932] 剩余票数:20 窗口<NSThread: 0x600002ab8040>{number = 4, name = (null)}
2019-04-09 11:57:49.072585+0800 MyNSOperation[3785:58934] 剩余票数:19 窗口<NSThread: 0x600002a87c00>{number = 3, name = (null)}
2019-04-09 11:57:49.072585+0800 MyNSOperation[3785:58932] 剩余票数:18 窗口<NSThread: 0x600002ab8040>{number = 4, name = (null)}
2019-04-09 11:57:51.076732+0800 MyNSOperation[3785:58934] 剩余票数:17 窗口<NSThread: 0x600002a87c00>{number = 3, name = (null)}
2019-04-09 11:57:51.076732+0800 MyNSOperation[3785:58932] 剩余票数:16 窗口<NSThread: 0x600002ab8040>{number = 4, name = (null)}
2019-04-09 11:57:53.081887+0800 MyNSOperation[3785:58932] 剩余票数:15 窗口<NSThread: 0x600002ab8040>{number = 4, name = (null)}
2019-04-09 11:57:53.081887+0800 MyNSOperation[3785:58934] 剩余票数:15 窗口<NSThread: 0x600002a87c00>{number = 3, name = (null)}
2019-04-09 11:57:55.084748+0800 MyNSOperation[3785:58934] 剩余票数:14 窗口<NSThread: 0x600002a87c00>{number = 3, name = (null)}
2019-04-09 11:57:55.084752+0800 MyNSOperation[3785:58932] 剩余票数:13 窗口<NSThread: 0x600002ab8040>{number = 4, name = (null)}
2019-04-09 11:57:57.087508+0800 MyNSOperation[3785:58934] 剩余票数:11 窗口<NSThread: 0x600002a87c00>{number = 3, name = (null)}
2019-04-09 11:57:57.087508+0800 MyNSOperation[3785:58932] 剩余票数:12 窗口<NSThread: 0x600002ab8040>{number = 4, name = (null)}
2019-04-09 11:57:59.092573+0800 MyNSOperation[3785:58932] 剩余票数:10 窗口<NSThread: 0x600002ab8040>{number = 4, name = (null)}
2019-04-09 11:57:59.092573+0800 MyNSOperation[3785:58934] 剩余票数:10 窗口<NSThread: 0x600002a87c00>{number = 3, name = (null)}
2019-04-09 11:58:01.096928+0800 MyNSOperation[3785:58934] 剩余票数:8 窗口<NSThread: 0x600002a87c00>{number = 3, name = (null)}
2019-04-09 11:58:01.096928+0800 MyNSOperation[3785:58932] 剩余票数:9 窗口<NSThread: 0x600002ab8040>{number = 4, name = (null)}
2019-04-09 11:58:03.102158+0800 MyNSOperation[3785:58934] 剩余票数:6 窗口<NSThread: 0x600002a87c00>{number = 3, name = (null)}
2019-04-09 11:58:03.102075+0800 MyNSOperation[3785:58932] 剩余票数:7 窗口<NSThread: 0x600002ab8040>{number = 4, name = (null)}
2019-04-09 11:58:05.106820+0800 MyNSOperation[3785:58934] 剩余票数:5 窗口<NSThread: 0x600002a87c00>{number = 3, name = (null)}
2019-04-09 11:58:05.106821+0800 MyNSOperation[3785:58932] 剩余票数:4 窗口<NSThread: 0x600002ab8040>{number = 4, name = (null)}
2019-04-09 11:58:07.110551+0800 MyNSOperation[3785:58932] 剩余票数:3 窗口<NSThread: 0x600002ab8040>{number = 4, name = (null)}
2019-04-09 11:58:07.110571+0800 MyNSOperation[3785:58934] 剩余票数:3 窗口<NSThread: 0x600002a87c00>{number = 3, name = (null)}
2019-04-09 11:58:09.115589+0800 MyNSOperation[3785:58932] 剩余票数:1 窗口<NSThread: 0x600002ab8040>{number = 4, name = (null)}
2019-04-09 11:58:09.115589+0800 MyNSOperation[3785:58934] 剩余票数:2 窗口<NSThread: 0x600002a87c00>{number = 3, name = (null)}
2019-04-09 11:58:11.117467+0800 MyNSOperation[3785:58932] 所有的火车票已售完
2019-04-09 11:58:11.117476+0800 MyNSOperation[3785:58934] 剩余票数:0 窗口<NSThread: 0x600002a87c00>{number = 3, name = (null)}
2019-04-09 11:58:13.120972+0800 MyNSOperation[3785:58934] 所有的火车票已售完

  可以看到,有多个票数得到的是重复的,错乱的。

所有我们要解决线程安全的问题,使用锁。在一个线程操作一个资源的时候,给这个资源加锁,不允许其他线程进行操作。IOS中实现线程加锁的方式是有很多种的。比如@synchronized,NSLock,NSRecursiveLock,NSConditionLock等等多种方式。我们这里使用NSLock的方式来给线程加锁。

我们来看下使用线程安全的代码:

/*
 线程安全的代码,使用NSLock锁
 初始化火车票数量,卖票窗口(线程安全),并开始卖票
 */
-(void)initTicketStatusSafe{
    NSLog(@"currentThread----%@",[NSThread currentThread]);
    self.ticketCount = 50;
    self.lock = [[NSLock alloc] init];
    //1.创建queue1,queue1代表北京售票窗口
    NSOperationQueue *queue1 = [[NSOperationQueue alloc] init];
    queue1.maxConcurrentOperationCount = 1;
    
    //2.创建queue2,queue2代表上海售票窗口
    NSOperationQueue *queue2 = [[NSOperationQueue alloc] init];
    queue2.maxConcurrentOperationCount = 1;
    
    //3.创建卖票操作op1
    NSBlockOperation *op1 = [NSBlockOperation blockOperationWithBlock:^{
        [self saleTicketSafe];
    }];
    //4.创建卖票操作op2
    NSBlockOperation *op2 = [NSBlockOperation blockOperationWithBlock:^{
        [self saleTicketSafe];
    }];
    //5.添加操作,开始卖票
    [queue1 addOperation:op1];
    [queue2 addOperation:op2];
}

//售卖火车票(线程安全)
-(void)saleTicketSafe{
    while (true) {
        //加锁
        [self.lock lock];
        if(self.ticketCount>0){
            //如果还有票的话,就继续卖票
            self.ticketCount--;
            NSLog(@"%@",[NSString stringWithFormat:@"剩余票数:%d,窗口:%@",self.ticketCount,[NSThread currentThread]]);
            [NSThread sleepForTimeInterval:2.0];
        }
        //解锁
        [self.lock unlock];
        if(self.ticketCount<=0){
            NSLog(@"所有票已经卖完");
            break;
        }
    }
}

  来看打印:

2019-04-09 15:29:44.182861+0800 MyNSOperation[10565:159368] currentThread----<NSThread: 0x60000063f780>{number = 1, name = main}
2019-04-09 15:29:44.186854+0800 MyNSOperation[10565:159459] 剩余票数:49,窗口:<NSThread: 0x600000663740>{number = 3, name = (null)}
2019-04-09 15:29:46.187749+0800 MyNSOperation[10565:159449] 剩余票数:48,窗口:<NSThread: 0x600000658bc0>{number = 4, name = (null)}
2019-04-09 15:29:48.190175+0800 MyNSOperation[10565:159459] 剩余票数:47,窗口:<NSThread: 0x600000663740>{number = 3, name = (null)}
2019-04-09 15:29:50.193962+0800 MyNSOperation[10565:159449] 剩余票数:46,窗口:<NSThread: 0x600000658bc0>{number = 4, name = (null)}
2019-04-09 15:29:52.199454+0800 MyNSOperation[10565:159459] 剩余票数:45,窗口:<NSThread: 0x600000663740>{number = 3, name = (null)}
2019-04-09 15:29:54.203206+0800 MyNSOperation[10565:159449] 剩余票数:44,窗口:<NSThread: 0x600000658bc0>{number = 4, name = (null)}
2019-04-09 15:29:56.207794+0800 MyNSOperation[10565:159459] 剩余票数:43,窗口:<NSThread: 0x600000663740>{number = 3, name = (null)}
2019-04-09 15:29:58.213412+0800 MyNSOperation[10565:159449] 剩余票数:42,窗口:<NSThread: 0x600000658bc0>{number = 4, name = (null)}
2019-04-09 15:30:00.214024+0800 MyNSOperation[10565:159459] 剩余票数:41,窗口:<NSThread: 0x600000663740>{number = 3, name = (null)}
2019-04-09 15:30:02.219388+0800 MyNSOperation[10565:159449] 剩余票数:40,窗口:<NSThread: 0x600000658bc0>{number = 4, name = (null)}
2019-04-09 15:30:04.224701+0800 MyNSOperation[10565:159459] 剩余票数:39,窗口:<NSThread: 0x600000663740>{number = 3, name = (null)}
2019-04-09 15:30:06.230349+0800 MyNSOperation[10565:159449] 剩余票数:38,窗口:<NSThread: 0x600000658bc0>{number = 4, name = (null)}
2019-04-09 15:30:08.233439+0800 MyNSOperation[10565:159459] 剩余票数:37,窗口:<NSThread: 0x600000663740>{number = 3, name = (null)}
2019-04-09 15:30:10.236390+0800 MyNSOperation[10565:159449] 剩余票数:36,窗口:<NSThread: 0x600000658bc0>{number = 4, name = (null)}
2019-04-09 15:30:12.239285+0800 MyNSOperation[10565:159459] 剩余票数:35,窗口:<NSThread: 0x600000663740>{number = 3, name = (null)}
2019-04-09 15:30:14.242919+0800 MyNSOperation[10565:159449] 剩余票数:34,窗口:<NSThread: 0x600000658bc0>{number = 4, name = (null)}
2019-04-09 15:30:16.246876+0800 MyNSOperation[10565:159459] 剩余票数:33,窗口:<NSThread: 0x600000663740>{number = 3, name = (null)}
2019-04-09 15:30:18.252321+0800 MyNSOperation[10565:159449] 剩余票数:32,窗口:<NSThread: 0x600000658bc0>{number = 4, name = (null)}
2019-04-09 15:30:20.253964+0800 MyNSOperation[10565:159459] 剩余票数:31,窗口:<NSThread: 0x600000663740>{number = 3, name = (null)}
2019-04-09 15:30:22.254687+0800 MyNSOperation[10565:159449] 剩余票数:30,窗口:<NSThread: 0x600000658bc0>{number = 4, name = (null)}
2019-04-09 15:30:24.255193+0800 MyNSOperation[10565:159459] 剩余票数:29,窗口:<NSThread: 0x600000663740>{number = 3, name = (null)}
2019-04-09 15:30:26.256679+0800 MyNSOperation[10565:159449] 剩余票数:28,窗口:<NSThread: 0x600000658bc0>{number = 4, name = (null)}
2019-04-09 15:30:28.261450+0800 MyNSOperation[10565:159459] 剩余票数:27,窗口:<NSThread: 0x600000663740>{number = 3, name = (null)}
2019-04-09 15:30:30.262594+0800 MyNSOperation[10565:159449] 剩余票数:26,窗口:<NSThread: 0x600000658bc0>{number = 4, name = (null)}
2019-04-09 15:30:32.267232+0800 MyNSOperation[10565:159459] 剩余票数:25,窗口:<NSThread: 0x600000663740>{number = 3, name = (null)}
2019-04-09 15:30:34.271705+0800 MyNSOperation[10565:159449] 剩余票数:24,窗口:<NSThread: 0x600000658bc0>{number = 4, name = (null)}
2019-04-09 15:30:36.275290+0800 MyNSOperation[10565:159459] 剩余票数:23,窗口:<NSThread: 0x600000663740>{number = 3, name = (null)}
2019-04-09 15:30:38.278967+0800 MyNSOperation[10565:159449] 剩余票数:22,窗口:<NSThread: 0x600000658bc0>{number = 4, name = (null)}
2019-04-09 15:30:40.284568+0800 MyNSOperation[10565:159459] 剩余票数:21,窗口:<NSThread: 0x600000663740>{number = 3, name = (null)}
2019-04-09 15:30:42.288319+0800 MyNSOperation[10565:159449] 剩余票数:20,窗口:<NSThread: 0x600000658bc0>{number = 4, name = (null)}
2019-04-09 15:30:44.293916+0800 MyNSOperation[10565:159459] 剩余票数:19,窗口:<NSThread: 0x600000663740>{number = 3, name = (null)}
2019-04-09 15:30:46.298411+0800 MyNSOperation[10565:159449] 剩余票数:18,窗口:<NSThread: 0x600000658bc0>{number = 4, name = (null)}
2019-04-09 15:30:48.301898+0800 MyNSOperation[10565:159459] 剩余票数:17,窗口:<NSThread: 0x600000663740>{number = 3, name = (null)}
2019-04-09 15:30:50.307369+0800 MyNSOperation[10565:159449] 剩余票数:16,窗口:<NSThread: 0x600000658bc0>{number = 4, name = (null)}
2019-04-09 15:30:52.309734+0800 MyNSOperation[10565:159459] 剩余票数:15,窗口:<NSThread: 0x600000663740>{number = 3, name = (null)}
2019-04-09 15:30:54.312124+0800 MyNSOperation[10565:159449] 剩余票数:14,窗口:<NSThread: 0x600000658bc0>{number = 4, name = (null)}
2019-04-09 15:30:56.313696+0800 MyNSOperation[10565:159459] 剩余票数:13,窗口:<NSThread: 0x600000663740>{number = 3, name = (null)}
2019-04-09 15:30:58.315219+0800 MyNSOperation[10565:159449] 剩余票数:12,窗口:<NSThread: 0x600000658bc0>{number = 4, name = (null)}
2019-04-09 15:31:00.317869+0800 MyNSOperation[10565:159459] 剩余票数:11,窗口:<NSThread: 0x600000663740>{number = 3, name = (null)}
2019-04-09 15:31:02.322281+0800 MyNSOperation[10565:159449] 剩余票数:10,窗口:<NSThread: 0x600000658bc0>{number = 4, name = (null)}
2019-04-09 15:31:04.326708+0800 MyNSOperation[10565:159459] 剩余票数:9,窗口:<NSThread: 0x600000663740>{number = 3, name = (null)}
2019-04-09 15:31:06.332550+0800 MyNSOperation[10565:159449] 剩余票数:8,窗口:<NSThread: 0x600000658bc0>{number = 4, name = (null)}
2019-04-09 15:31:08.336064+0800 MyNSOperation[10565:159459] 剩余票数:7,窗口:<NSThread: 0x600000663740>{number = 3, name = (null)}
2019-04-09 15:31:10.341717+0800 MyNSOperation[10565:159449] 剩余票数:6,窗口:<NSThread: 0x600000658bc0>{number = 4, name = (null)}
2019-04-09 15:31:12.342312+0800 MyNSOperation[10565:159459] 剩余票数:5,窗口:<NSThread: 0x600000663740>{number = 3, name = (null)}
2019-04-09 15:31:14.347439+0800 MyNSOperation[10565:159449] 剩余票数:4,窗口:<NSThread: 0x600000658bc0>{number = 4, name = (null)}
2019-04-09 15:31:16.348122+0800 MyNSOperation[10565:159459] 剩余票数:3,窗口:<NSThread: 0x600000663740>{number = 3, name = (null)}
2019-04-09 15:31:18.352838+0800 MyNSOperation[10565:159449] 剩余票数:2,窗口:<NSThread: 0x600000658bc0>{number = 4, name = (null)}
2019-04-09 15:31:20.355310+0800 MyNSOperation[10565:159459] 剩余票数:1,窗口:<NSThread: 0x600000663740>{number = 3, name = (null)}
2019-04-09 15:31:22.358857+0800 MyNSOperation[10565:159449] 剩余票数:0,窗口:<NSThread: 0x600000658bc0>{number = 4, name = (null)}
2019-04-09 15:31:24.363256+0800 MyNSOperation[10565:159449] 所有票已经卖完
2019-04-09 15:31:24.363263+0800 MyNSOperation[10565:159459] 所有票已经卖完

  可以看出,在使用了线程安全机制之后,票数正常了。

猜你喜欢

转载自www.cnblogs.com/howlaa/p/10677242.html
今日推荐