挖墙脚的小猪 挖墙脚的小猪
你就是想的太多而读书太少
关注数: 113 粉丝数: 283 发帖数: 42,553 关注贴吧数: 68
如何实现iOS中的线程安全 ①互斥锁 @synchronized(self) { NSLog(@"我是竞争资源,只能同时被一个线程访问"); } ②信号量 dispatch_semaphore_t semaphore = dispatch_semaphore_create(1);//创建数量为1的信号量 dispatch_time_t timeout = dispatch_time(DISPATCH_TIME_NOW, 3 * NSEC_PER_SEC);//超时时间 dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{ dispatch_semaphore_wait(semaphore, timeout);//调用wait 信号量减1 NSLog(@"线程1 开始使用竞争资源"); sleep(1); NSLog(@"线程1 结束使用竞争资源"); dispatch_semaphore_signal(semaphore);//调用signal 信号量加1 }); dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{ sleep(2); dispatch_semaphore_wait(semaphore, timeout); NSLog(@"线程2 开始使用竞争资源"); sleep(1); NSLog(@"线程2 结束使用竞争资源"); dispatch_semaphore_signal(semaphore); }); 信号量为1的时候,可以作为锁来使用,当等待的情况发生较少的时候,性能很高 ③NSLock NSLock *lock = [[NSLock alloc] init]; dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{ [lock lock]; NSLog(@"线程1 开始享用竞争资源"); sleep(1); NSLog(@"线程1 结束享用竞争资源"); [lock unlock]; }); dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{ [lock lock]; NSLog(@"线程2 开始享用竞争资源"); sleep(1); NSLog(@"线程2 结束享用竞争资源"); [lock unlock]; }); ④NSRecursiveLock 递归锁可以被同一个线程多次访问加锁 不会引起死锁问题 NSRecursiveLock *recursiveLock = [[NSRecursiveLock alloc] init]; dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{ static void(^RecursiveMethod)(int); RecursiveMethod = ^(int value) { [recursiveLock lock];//加锁 可以被同一个线程重复加锁 而不会造成死锁 if (value > 0) { NSLog(@"value = %d", value); sleep(1); RecursiveMethod(value - 1);//递归调用 } [recursiveLock unlock];//解锁 }; RecursiveMethod(5); }); 当把上述的NSRecursiveLock替换为NSLock的时候,就会发生死锁 ⑤NSConditionLock 条件锁可以给加锁和解锁传递条件 NSInteger condition_a = 0; NSInteger condition_b = 1; NSConditionLock *conditionLock = [[NSConditionLock alloc] initWithCondition:condition_a];//刚开始的条件是a dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{ while (1) { [conditionLock lockWhenCondition:condition_a];//只有在条件a下才加锁 NSLog(@"aaaaaa"); sleep(1); [conditionLock unlockWithCondition:condition_b];//解锁并进入条件b } }); dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{ while (1) { [conditionLock lockWhenCondition:condition_b];//只有在条件b下才加锁 NSLog(@"bbbbbb"); sleep(1); [conditionLock unlockWithCondition:condition_a];//解锁并进入条件a } }); ⑥pthread_mutex 这是一种c语言定义下的加锁方式。 __block pthread_mutex_t mutex; pthread_mutex_init(&mutex, NULL); dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{ pthread_mutex_lock(&mutex); NSLog(@"线程1 开始使用竞争资源"); sleep(1); NSLog(@"线程1 结束使用竞争资源"); pthread_mutex_unlock(&mutex); }); dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{ sleep(1); pthread_mutex_lock(&mutex); NSLog(@"线程2 开始使用竞争资源"); sleep(1); NSLog(@"线程2 结束使用竞争资源"); pthread_mutex_unlock(&mutex); }); ⑦OSSpinLock 自旋锁,虽然性能高,但是目前存在优先级翻转问题,不建议使用。 性能上 OSSpinLock、dispatch_semaphore远高于其他,但是由于OSSpinLock存在问题,所以推荐使用dispatch_semaphore。
iOS开发中如何实现多线程 iOS中实现多线程的四种方案 pthread:基于c语言的多线程方案 使用起来比较复杂 一般很少用 NSThread:面向对象的多线程方案 使用简单 但是功能简单 无法处理高级问题 GCD:合理利用多核处理器的多线程方案 功能齐全 一般都用这个 NSOperation和NSOperationQueue:对GCD的封装 更加面向对象 关于GCD: 关于任务:其实就是block里面的内容 关于任务的执行方式,即async(异步)和sync(同步)的区别:async里面执行的任务不会阻塞当前线程 而sync则会阻塞当前线程 关于队列:存放任务 串行队列的任务会依照添加的顺序一个执行完成之后才执行下一个 而并行队列里的任务则会一添加上就立刻并发执行 主队列:获取方式dispatch_get_main_queue() 是一个串行队列 所有刷新UI的操作都是放在主队列中进行的 全局队列:获取方式dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0) 根据优先级不同总共存在四个 获取方式中的第一个参数为优先级参数 是并发队列 自定义队列:获取方式dispatch_queue_create("com.xiaoying.testQueue1", DISPATCH_QUEUE_SERIAL / DISPATCH_QUEUE_CONCURRENT) 可以自由创建串行或者并行队列 死锁 举个栗子: dispatch_sync(dispatch_get_main_queue(), ^{ NSLog(@"111111111"); }); 以上代码会产生死锁。 当执行到sync的时候,由于是sync方式执行,线程阻塞,会去等待打印1的任务执行完毕。 而由于队列是串行的,打印1的任务又会等待主队列里的任务,也就是sync方法执行完毕。 由此产生相互等待的情况,造成死锁。 队列组:如果我们希望当若干队列里的任务都执行完成之后 我们能够接受到通知 那就可以使用队列组 举个栗子: dispatch_group_t testGroup = dispatch_group_create(); dispatch_queue_t testQueue1 = dispatch_queue_create("com.xiaoying.testQueue1", DISPATCH_QUEUE_SERIAL); dispatch_queue_t testQueue2 = dispatch_queue_create("com.xiaoying.testQueue2", DISPATCH_QUEUE_CONCURRENT); dispatch_group_async(testGroup, testQueue1, ^{//将一个在指定队列中执行的block和一个group关联 只能以异步方式执行任务 NSLog(@"testQueue1 111111"); NSLog(@"testQueue1 222222"); NSLog(@"testQueue1 333333"); NSLog(@"testQueue1 444444"); NSLog(@"testQueue1 555555"); }); dispatch_group_async(testGroup, testQueue2, ^{//将一个在指定队列中执行的block和一个group关联 只能以异步方式执行任务 NSLog(@"testQueue2 111111"); NSLog(@"testQueue2 222222"); NSLog(@"testQueue2 333333"); NSLog(@"testQueue2 444444"); NSLog(@"testQueue2 555555"); }); dispatch_group_notify(testGroup, dispatch_get_main_queue(), ^{//当和group关联的block全部执行完毕的时候 在指定的队列执行block NSLog(@"mainQueue 111111"); }); 屏障:除了dispatch_asyn和dispatch_sync的方式提交任务以外,还可以以dispatch_barrier_async和dispatch_barrier_sync的 方式提交任务,这两种提交只有在队列是并发队列的情况下生效(否则就和没有barrier一样),当把一个任务通过barrier的方式提交的时候 ,它会等待队列中的已提交的所有任务完成,然后才会去执行自己,并且所有后续提交给这个队列的任务将暂停执行,直到自己执行完毕。同样 的,async和sync的方式的区别是是否阻塞当前线程。举个栗子: dispatch_queue_t testQueueConcurrent = dispatch_queue_create("com.xiaoying.testQueue2", DISPATCH_QUEUE_CONCURRENT); dispatch_async(testQueueConcurrent, ^{ NSLog(@"111"); }); dispatch_async(testQueueConcurrent, ^{ NSLog(@"222"); }); dispatch_async(testQueueConcurrent, ^{ NSLog(@"333"); }); dispatch_barrier_async(testQueueConcurrent, ^{ NSLog(@"444"); }); dispatch_async(testQueueConcurrent, ^{ NSLog(@"555"); }); dispatch_async(testQueueConcurrent, ^{ NSLog(@"666"); }); dispatch_async(testQueueConcurrent, ^{ NSLog(@"777"); });
首页 1 2 下一页