iOS 多线程iOS 多线程iOS进阶指南

iOS多线程-线程同步/线程安全

2016-02-25  本文已影响2083人  Yasin的简书

线程同步同步线程是两个概念。不要搞混了。

同步线程:串行执行任务的线程,会把你的同步代码一行一行的执行下去,即使是在block里面。
异步线程:并行执行的线程,代码会放在另外一块区域去执行,执行完毕之后返回结果。
线程异步:我也不知道表达的什么,这个词汇是不应该存在,可以理解为异步线程。
线程同步:是指多个线程同时访问一个资源时可能存在竞争问题提供的解决方案,使多个线程可以对同一个资源进行操作,比如线程A为数组M添加了一个数据,线程B可以接收到添加数据后的数组M。线程同步就是线程之间相互的通信。

常见比如线程内操作了一个线程外的变量,这个时候一定要考虑线程安全和同步。

- (void)getIamgeName:(NSMutableArray *)imageNames{//假如每个进来的都是一个线程
    //1.imageNames是线程外的变量,这个时候就需要考虑线程安全
    /*2.NSMutableArray *array = [[NSMutableArray alloc]initWithArray:imageNames];
    这里如果新生成一个array,下面也把imageNames换成array就不需要考虑线程安全,但是这样array.count判断永远大于0,也就是永远等于imageNames.count
     */
    NSString *imageName;
    if (imageNames.count>0) {
        imageName = [imageNames lastObject];
        [imageNames removeObject:imageName];
    }
}

同步异步任务

这里有个概念容易混搅:
在GCD里面创建一个并行队列,如果向队列添加同步任务,任务还是同步执行的。主线程会等待同步任务执行,同步任务会卡主线程,如果添加了同步任务需要注意主线程的响应问题。
GCD的队列只是定义了队列里面的任务是怎么执行的,是串行还是并行,并没有定义任务是在异步线程执行还是同步线程执行。

    dispatch_queue_t globalQueue = dispatch_queue_create([@"com.yasin.dispatchqueue" cStringUsingEncoding:NSASCIIStringEncoding], DISPATCH_QUEUE_CONCURRENT);;
    for (int i=0; i<100; i++) {
        dispatch_sync(globalQueue, ^(){
            [self getIamgeName];
            for (int m =100*(100-i); m>0; m--) {
                /**
                 *  i从0到100,m就是10000,9900,9800---100减减到0,
                 所以这里的任务耗时是越来越少
                 如果是一个接着一个执行就会是正序输出i,
                 如果是一起执行最后输入,也许不会倒序输出i,但至少是乱序的
                 */
                BOOL ss = [[NSUserDefaults standardUserDefaults]boolForKey:@"随便一个key"];
                if (ss) {
                    //读取和判断很耗时
                    //模拟耗时操作
                }
            }
            NSLog(@"%d",i);
        });
    }

这里会一个接着一个执行同步线程的任务,并不会出现几个线程同时执行的现象。你规定了要同步一个一个执行线程任务怎么可能会并行执行多个任务。这个代码书写逻辑就不对。

--小结-- 其实只要不做傻事就不会出问题,要一个一个执行的任务就放在串行队列里面,需要异步就异步,需要同步就同步(异步不卡主线程,同步卡主线程);如果想要并行执行多个任务,就放在并行队列里面,开异步线程去做。

线程同步的方法

performSelector:withObject:afterDelay:
performSelectorInBackground:withObject:
performSelector:onThread:withObject:waitUntilDone:

代码:

[self performSelector:@selector(test:) withObject:nil afterDelay:1];
[self performSelectorInBackground:@selector(test:) withObject:nil];
//等效于[NSThread detachNewThreadSelector:@selector(test:) toTarget:self withObject:nil];

代码2:

-(void)viewDidLoad
{
    [super viewDidLoad];
    
    [self threadInfo:@"UI"];
    
    _isNewThreadAborted = NO;
    _thread = [[NSThread alloc] initWithTarget:self selector:@selector(newThread:) object:nil];
    //开始线程
    [_thread start];
    //在另一个线程中的Run Loop中执行Selector
    [self performSelector:@selector(test:) onThread:_thread withObject:nil waitUntilDone:NO];
}
//在新线程中创建并开始一个NSRunLoop
-(void)newThread:(id)obj
{
    @autoreleasepool
    {
        NSRunLoop *currentRunLoop = [NSRunLoop currentRunLoop];
        while (!_isNewThreadAborted)
        {
            [currentRunLoop runMode:NSDefaultRunLoopMode beforeDate:[NSDate distantFuture]];
        }
        NSLog(@"线程停止");
    }
}
//Selector执行
-(void)test:(id)obj
{
    [self threadInfo:@"test"];
    _isNewThreadAborted = YES;
}
-(void)threadInfo:(NSString*)category
{
    NSLog(@"%@ - %@", category, [NSThread currentThread]);
}

并行并发

并发编程、并发程序,和并行计算机。
并发性与软件结构有关,而并行性与硬件有关。
也就是说,并发就是多线程编程,并行就是多核处理器。

天下武功出少林

这里推荐一个特别好的文章iOS多线程编程指南(四)线程同步

后续我会着重研究线程锁这一块

上一篇下一篇

猜你喜欢

热点阅读