你如何使用GCD安全地锁定变量?

时间:2014-06-28 00:48:36

标签: cocoa concurrency grand-central-dispatch

我有一个NSMutableArray我需要从我调度的多个块中添加对象。这是确保阵列安全更改的可接受方式吗?这些已经从内部和NSOperation发送并在后台运行。我正在连续加载该线程中的数据,但是一次加载一个位置列表变得非常慢。

NSMutableArray *weatherObjects = [[NSMutableArray alloc] init];
ForecastDownloader *forecastDownloader = [[ForecastDownloader alloc] init];

dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
dispatch_group_t group = dispatch_group_create();

dispatch_queue_t serialQueue;
serialQueue = dispatch_queue_create("us.mattshepherd.ForecasterSerialQueue", NULL);

for (NSDictionary *theLocation in self.weatherLocations) {

    // Add a task to the group
    dispatch_group_async(group, queue, ^{
        NSLog(@"dispatching...");
        int i = 0;
        WeatherObject *weatherObject = [forecastDownloader getForecast:[theLocation objectForKey:@"lat"] lng:[theLocation objectForKey:@"lng"] weatherID:[[theLocation objectForKey:@"id"] intValue]];

        }
        if(!weatherObject){
            //need to implement delegate method to show problem updating weather
            NSLog(@"problem updating weather data");
        }else{
            NSLog(@"got weather for location...");
            dispatch_sync(serialQueue, ^{
                [weatherObjects addObject:weatherObject];
            });


        }
    });

}
// wait on the group to block the current thread.
dispatch_group_wait(group, DISPATCH_TIME_FOREVER);

NSLog(@"finished getting weather for all locations...");
//we will now do something with the weatherObjects

1 个答案:

答案 0 :(得分:1)

这不会起作用,因为你每次都要制作一个新的锁,而不是使用一个锁来锁定变量(类比:想象一下房间的锁门。如果每个人都有一个带锁的自己的门,它他们锁定它并不重要,因为其他人都会自己进门。)

您可以为所有迭代使用单个NSLock,或者(基本上等效地)使用单个串行调度队列。