IOS多线程同步问题

来源:互联网 发布:爱奇艺mac版 编辑:程序博客网 时间:2024/06/07 20:04

        在多线程开发中,要注意避免的是多个线程在同一时间对某数据进行读或写所造成的不可预见错误。因此在不同线程中需要对公共数据进行互斥的访问,最常见的是生产者与消费者问题。

1. 同步块或者NSLock

        同步块或者NSLock实现的效果差不多,都是进行加锁-操作-解锁,以此达到互斥访问的效果。

        在一个代码块中进行加锁可以实现不同线程对该代码块的互斥访问。在多个代码块中使用同一个信号量进行加锁则不同代码块之间也能实现互斥访问。即加锁解锁的本质是对信号量的原子处理。

//生产者-同步代码块,括号参数为自定义信号量-(void)synchronizeFunc1 {        @synchronized (self) {        if(count < 1000) {            count += 100;            NSLog(@"P count is %d", count);        }    }}//消费者-同步代码块-(void)synchronizeFunc2 {        @synchronized (self) {        if(count > 0) {            count -= 100;            NSLog(@"C count is %d", count);        }    }}//生产者-NSLock,一个NSLock对象就是一个信号量-(void)synchronizeFunc3 {        [nsLock lock];    if(count < 1000) {        count += 100;        NSLog(@"P count is %d", count);    }    [nsLock unlock];}//消费者-NSlock-(void)synchronizeFunc4 {        [nsLock lock];    if(count > 0) {        count -= 100;        NSLog(@"C count is %d", count);    }    [nsLock unlock];}

2. NSConditon

        很明显上面两种操作中,所有的线程都是独立运行的,线程之间没有任何通信或者说协作。如果消费者获得了lock,但是此时count<0,那么消费者函数将解锁并退出,也就是说取钱失败。如果我们想,取消操作中发现count<0后,可以进行等待生产者存钱,之后再取钱,这时就需要用到NSCondition了。NSCondition在NSLock的基础上,多加了wait函数和signal/broadcast函数,可以是获得了信号量但是却操作条件不足满的线程释放信号量进行等待,在条件满足之后再被唤醒继续加锁执行之前的操作。

        下面有一个测试的例子看wait做了什么

    //2个消费者    for(int i=0; i<2; i++){        NSThread* thread1 = [[NSThread alloc]initWithTarget:self selector:@selector(synchronizeFunc6) object:nil];        [thread1 start];    }    //1个生产者    NSThread* thread2 = [[NSThread alloc]initWithTarget:self selector:@selector(synchronizeFunc5) object:nil];    [thread2 start];//生产者-NSConditon,一个NSConditon对象就是一个信号量-(void)synchronizeFunc5 {        [condition lock];    NSLog(@"P Enter");    if(count >= 1000){        [condition wait];        NSLog(@"P wait");    }    else {        count += 100;        NSLog(@"P count is %d", count);        [condition broadcast];    }    [condition unlock];    NSLog(@"P conditon");}//消费者-NSConditon-(void)synchronizeFunc6 {        [condition lock];    NSLog(@"C Enter");    if(count <= 0)    {        [condition wait];        NSLog(@"C Wait");    }    else {        count -= 100;        NSLog(@"C count is %d", count);        [condition broadcast];    }    [condition unlock];    NSLog(@"C condition");}

程序输出:



上面先启动了两个消费者线程,由于count<0所以都进入了等待。在启动生产者执行了boradcast唤醒之后,两个消费者线程又分别继续执行之前的程序,并不会因为count的改变而去执行else部分,因为if判断是在wait之前执行的,唤醒后将直接在wait部分继续往下执行。

这篇博客,讲了一些property的atomic相关的东西:

点击打开链接

原创粉丝点击