简体   繁体   English

线程安全:NSOperationQueue + [array addObject]

[英]Thread safety: NSOperationQueue + [array addObject]

I could not find any examples how to deal with the same (class) variable when operation queue is used. 使用操作队列时,我找不到如何处理相同(类)变量的任何示例。 In C & threads its about mutexes. 在C&线程中它关于互斥体。 So, what happens when NSOperationQueue starts a thread for operation and class variable is modified? 那么,当NSOperationQueue启动操作线程并修改类变量时会发生什么? Is it thread safe? 它是线程安全的吗? Thank you. 谢谢。

@interface MyTest {
    NSMutableArray *_array;
}
@end

-(id)init
{
    ...
    _array = [NSMutableArray new]; // class variable

        // queue time consuming loading
    NSOperationQueue *queue = [NSOperationQueue new];
    NSInvocationOperation *operation =
        [NSInvocationOperation initWithTarget:self
                                     selector:@selector(populate)
                                       object:nil];
    [queue addOperation:operation];

        // start continuous processing
    [NSTimer scheduledTimerWithTimeInterval:0.1
                                     target:self
                                   selector:@selector(processing)
                                   userInfo:nil
                                    repeats:YES];
    ...
}

-(void)populate
{
    while (...)
    {
        id element = ...; // time consuming

            // modify class variable "_array" from operation's thread (?)
        [_array addObject:element];

            // Ok, I can do instead of addObject
            // performSelectorOnMainThread:withObject:waitUntilDone:
            // but is it the only way? Is it needed?
    }
}

    // access and/or modify class variable "_array"
-(void)processing
{
    NSLog(@"array.count = %d", array.count);
    for (id i in _array)
    {
        [_array addObject:[NSNumber numberWithInt:rand() % 100]];
            // etc...
    }
}

No, this is not thread safe, if you start a thread that does some work on a class variable that can be modified by some other thread then its not thread safe, if processing is called from some thread while populate is running on another then you might get an exception when the foreach loop sees that the array has been modified, though you will get that exception anyway as you are modifying the array inside the foreach loop in your example (you shouldnt do that, and the program will throw an exception )... One way to get around this can be with a synchronized block on the array, it will ensure that the synchronized blocks wont be executed at the same time, the thread blocks until one synchronized block finishes, for example 不,这不是线程安全的,如果启动的线程在可以由其他线程修改的类变量上执行某些工作,则它不是线程安全的,如果在填充正在另一个线程上运行时从某个线程调用处理,则您当foreach循环看到数组已被修改时,可能会收到一个异常,尽管您在示例中在foreach循环内修改数组时仍会得到该异常(您不应该这样做,程序会抛出一个异常) ...解决此问题的一种方法是在数组上使用同步块,它将确保同步块不会在同一时间执行,例如线程块直到一个同步块完成为止。

    -(void)populate
    {


        while (...)
        {
            id element = ...; // time consuming

                // modify class variable "_array" from operation's thread (?)
      @synchronized(_array)
        {
            [_array addObject:element];

        }          // Ok, I can do instead of addObject
                // performSelectorOnMainThread:withObject:waitUntilDone:
                // but is it the only way? Is it needed?
        }

    }

        // access and/or modify class variable "_array"
    -(void)processing
    {


          @synchronized(_array)
         {
            NSLog(@"array.count = %d", array.count);
            for (id i in _array)
            {
                //you shouldnt modify the _array here you will get an exception
                    // etc...
            }
        }
    }

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM