异步并发队列,同步并发队列,异步串行队列,同步串行队列总结

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/u012581760/article/details/83899278
#import "ViewController.h"

@interface ViewController ()
@property (assign, nonatomic) int ticketCount;
@end

@implementation ViewController

- (void)viewDidLoad {
    [super viewDidLoad];
    // 设置初始值
    self.ticketCount = 10;
}

- (void)saleTicket
{
    int oldTicket = self.ticketCount;
    sleep(.2);// 为了使多线程安全问题更加突出明显
    oldTicket--;
    self.ticketCount = oldTicket;
    NSLog(@"还剩%d张票,-%@",oldTicket,[NSThread currentThread]);
}


- (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event
{
    // 1 异步并发队列 (执行过程,(任务同步执行)执行的每一个任务都可能是开启新的不同的线程,出现多线程安全隐患问题)
    /*
     2018-11-09 08:10:57.504969+0800 MultiThread[4165:33899] 还剩7张票,-<NSThread: 0x604000275480>{number = 5, name = (null)}
     2018-11-09 08:10:57.505043+0800 MultiThread[4165:33900] 还剩6张票,-<NSThread: 0x604000267fc0>{number = 6, name = (null)}
     2018-11-09 08:10:57.505131+0800 MultiThread[4165:33894] 还剩9张票,-<NSThread: 0x600000274e80>{number = 3, name = (null)}
     2018-11-09 08:10:57.505157+0800 MultiThread[4165:33392] 还剩8张票,-<NSThread: 0x604000268f80>{number = 4, name = (null)}
     
     */
    //    [self saleTicketsByAsyncConcurrentQueue];
    
    
    
    
    // 2(1) 同步并发队列 (执行过程,(任务依次执行)执行的每一个任务都是在主线程执行(创建新的线程的话,在新的这个子线程中执行),不会出现线程安全隐患问题)
    /*
     2018-11-09 08:14:09.411497+0800 MultiThread[4513:36117] 还剩9张票,-<NSThread: 0x60000007e3c0>{number = 1, name = main}
     2018-11-09 08:14:09.413190+0800 MultiThread[4513:36117] 还剩8张票,-<NSThread: 0x60000007e3c0>{number = 1, name = main}
     2018-11-09 08:14:09.413855+0800 MultiThread[4513:36117] 还剩7张票,-<NSThread: 0x60000007e3c0>{number = 1, name = main}
     2018-11-09 08:14:09.414058+0800 MultiThread[4513:36117] 还剩6张票,-<NSThread: 0x60000007e3c0>{number = 1, name = main}
     
     */
    //    [self saleTicketsBySyncConcurrrentQueue];
    
    
    
    // 2(2) 同步并发队列 (执行过程,(任务依次执行)执行的每一个任务都是在新创建这个子线程中执行(没有创建新的线程的话,默认在主线程执行),不会出现线程安全隐患问题)
    /*
     2018-11-09 08:22:48.043307+0800 MultiThread[5345:43339] 还剩9张票,-<NSThread: 0x600000476940>{number = 3, name = (null)}
     2018-11-09 08:22:48.044512+0800 MultiThread[5345:43339] 还剩8张票,-<NSThread: 0x600000476940>{number = 3, name = (null)}
     2018-11-09 08:22:48.044892+0800 MultiThread[5345:43339] 还剩7张票,-<NSThread: 0x600000476940>{number = 3, name = (null)}
     2018-11-09 08:22:48.045262+0800 MultiThread[5345:43339] 还剩6张票,-<NSThread: 0x600000476940>{number = 3, name = (null)}
     */
    //      NSThread *mySubThread = [[NSThread alloc]initWithBlock:^{
    //            [self saleTicketsBySyncConcurrentQueueInSubThread];
    //        }];
    //        [mySubThread start];
    
    
    // 3 异步串行队列  (执行过程,任务依次执行),异步是具备开启线程的能力,所以任务是在新开启的线程中执行的
    /*
     2018-11-09 08:29:45.335619+0800 MultiThread[5982:48675] 还剩9张票,-<NSThread: 0x604000465900>{number = 3, name = (null)}
     2018-11-09 08:29:45.337492+0800 MultiThread[5982:48675] 还剩8张票,-<NSThread: 0x604000465900>{number = 3, name = (null)}
     2018-11-09 08:29:45.339066+0800 MultiThread[5982:48675] 还剩7张票,-<NSThread: 0x604000465900>{number = 3, name = (null)}
     2018-11-09 08:29:45.339200+0800 MultiThread[5982:48675] 还剩6张票,-<NSThread: 0x604000465900>{number = 3, name = (null)}
     */
    //    [self saleTicketsByAsyncSerialQueue];
    
    
    // 4(1) 同步串行队列 (执行过程,默认在主线程中执行,没有开启新的线程),任务依次执行
    /*
     2018-11-09 08:32:52.110500+0800 MultiThread[6285:50954] 还剩9张票,-<NSThread: 0x60000007db00>{number = 1, name = main}
     2018-11-09 08:32:52.111387+0800 MultiThread[6285:50954] 还剩8张票,-<NSThread: 0x60000007db00>{number = 1, name = main}
     2018-11-09 08:32:52.112358+0800 MultiThread[6285:50954] 还剩7张票,-<NSThread: 0x60000007db00>{number = 1, name = main}
     2018-11-09 08:32:52.112976+0800 MultiThread[6285:50954] 还剩6张票,-<NSThread: 0x60000007db00>{number = 1, name = main}
     
     */
    //    [self saleTicketsBySyncSerialQueue];
    
    
    // 4(2) 同步串行 (执行过程,在新创建的线程中执行,同步没有开启新线程的能力),任务依次执行
    /*
     2018-11-09 08:34:42.703053+0800 MultiThread[6466:52766] 还剩9张票,-<NSThread: 0x60000026b780>{number = 3, name = (null)}
     2018-11-09 08:34:42.703639+0800 MultiThread[6466:52766] 还剩8张票,-<NSThread: 0x60000026b780>{number = 3, name = (null)}
     2018-11-09 08:34:42.704769+0800 MultiThread[6466:52766] 还剩7张票,-<NSThread: 0x60000026b780>{number = 3, name = (null)}
     2018-11-09 08:34:42.706400+0800 MultiThread[6466:52766] 还剩6张票,-<NSThread: 0x60000026b780>{number = 3, name = (null)}
     */
    //    NSThread *mySyncSerailQueueInSubThread = [[NSThread alloc]initWithBlock:^{
    //        [self saleTicketsBySyncSerialQueue];
    //    }];
    //    [mySyncSerailQueueInSubThread start];
    //
    
    
}

#pragma mark - 创建异步并发队列
- (void)saleTicketsByAsyncConcurrentQueue
{
    dispatch_queue_t asyncConQueue = dispatch_queue_create("myAsyncConcurrentQueue", DISPATCH_QUEUE_CONCURRENT);
    
    dispatch_async(asyncConQueue, ^{
        [self saleTicket];
    });
    
    dispatch_async(asyncConQueue, ^{
        [self saleTicket];
    });
    
    dispatch_async(asyncConQueue, ^{
        [self saleTicket];
    });
    
    dispatch_async(asyncConQueue, ^{
        [self saleTicket];
    });
}


#pragma mark - 创建同步并发队列(未创建新的线程,默认同步并发,是在主线程进行)
- (void)saleTicketsBySyncConcurrrentQueueInMain
{
    dispatch_queue_t syncConcurrentQueue = dispatch_queue_create("mySyncConcurrentQueue", DISPATCH_QUEUE_CONCURRENT);
    dispatch_sync(syncConcurrentQueue, ^{
        [self saleTicket];
    });
    dispatch_sync(syncConcurrentQueue, ^{
        [self saleTicket];
    });
    dispatch_sync(syncConcurrentQueue, ^{
        [self saleTicket];
    });
    dispatch_sync(syncConcurrentQueue, ^{
        [self saleTicket];
    });
}

#pragma mark - 创建同步并发队列(创建新的线程,同步并发会在新创建的这个线程中串行执行任务)
- (void)saleTicketsBySyncConcurrentQueueInSubThread
{
    dispatch_queue_t syncConcurrentQueueInSubThread = dispatch_queue_create("mySyncConcurrentQueueInSubThread", DISPATCH_QUEUE_CONCURRENT);
    dispatch_sync(syncConcurrentQueueInSubThread, ^{
        [self saleTicket];
    });
    dispatch_sync(syncConcurrentQueueInSubThread, ^{
        [self saleTicket];
    });
    dispatch_sync(syncConcurrentQueueInSubThread, ^{
        [self saleTicket];
    });
    dispatch_sync(syncConcurrentQueueInSubThread, ^{
        [self saleTicket];
    });
}



#pragma mark - 创建异步串行队列
- (void)saleTicketsByAsyncSerialQueue
{
    
    dispatch_queue_t asyncSerialQueue = dispatch_queue_create("myAsyncSerialQueue", DISPATCH_QUEUE_SERIAL);
    
    dispatch_async(asyncSerialQueue, ^{
        [self saleTicket];
    });
    
    dispatch_async(asyncSerialQueue, ^{
        [self saleTicket];
    });
    
    dispatch_async(asyncSerialQueue, ^{
        [self saleTicket];
    });
    
    dispatch_async(asyncSerialQueue, ^{
        [self saleTicket];
    });
    
}

#pragma mark - 创建同步串行队列
- (void)saleTicketsBySyncSerialQueue
{
    dispatch_queue_t syncSerialQueue = dispatch_queue_create("mySyncSerialQueue", DISPATCH_QUEUE_SERIAL);
    
    dispatch_sync(syncSerialQueue, ^{
        [self saleTicket];
    });
    
    dispatch_sync(syncSerialQueue, ^{
        [self saleTicket];
    });
    
    dispatch_sync(syncSerialQueue, ^{
        [self saleTicket];
    });
    
    dispatch_sync(syncSerialQueue, ^{
        [self saleTicket];
    });
    
}

@end

总结
1 引发的问题
异步并发会引起多线程安全隐患问题.
2 问题的解决方案
多线程安全问题的解决方案是:使用线程同步(同步就是按预定的先后次序进行),常用的线程同步技术是加锁
3 锁的类型及其性能比较

  1. OSSpinLock 自旋锁
  2. os_unfair_lock
  3. pthread_mutex
  4. disptach_semaphare信号量
  5. disptach_queue(DISPATCH_QUEUE_SERIAL)串行队列
  6. NSLock
  7. NSRecursiveLock
  8. NSCondition
  9. NSConditionLock
  10. @synchronized
    具体各种类型的锁在下篇文章中讲解

猜你喜欢

转载自blog.csdn.net/u012581760/article/details/83899278