Доступ к изменяемой коллекции Cocoa Threadsafe - PullRequest
2 голосов
/ 01 декабря 2008

Я создаю изменяемый массив, совместимый с KVC / KVO, на одном из моих объектов рекомендуемым способом:

@interface Factory {
    NSMutableArray *widgets;
}
- (NSArray *)widgets;
- (void)insertObject:(id)obj inWidgetsAtIndex:(NSUInteger)idx;
- (void)removeObjectFromWidgetsAtIndex:(NSUInteger)idx;
@end

Очевидно, что это сложная проблема с безопасностью потоков. В методах insert и remove я ограничиваю доступ к массиву, чтобы предотвратить одновременное изменение, как рекомендуется .

Мой вопрос: как правильно реализовать аксессор widgets? Вот моя реализация:

- (NSArray *)widgets {
    [widgetLock lock];
    NSArray *a = [[widgets copy] autorelease];
    [widgetLock unlock];
    return a;
}

Поток безопасен?

Ответы [ 3 ]

2 голосов
/ 02 декабря 2008

Ваш widgets метод доступа должен быть в порядке, хотя вы должны знать, что ни один из объектов в этом массиве не заблокирован. Таким образом, вы можете столкнуться с проблемами, пытаясь одновременно запустить код вроде

[[[myFactory widgets] objectAtIndex:7] setName:@"mildred"];

и

[myTextField setStringValue:[[[myFactory widgets] objectAtIndex:7] name]]; // mildred? or something else?

Поскольку объекты в вашем массиве не заблокированы, вы можете столкнуться с условиями гонки или проблемами типа читателей / писателей. Разве многопоточность не радость?

С другой стороны, для соответствия KVC я бы посоветовал использовать objectInWidgetsAtIndex: и countOfWidgets вместо средства доступа widgets. Помните, KVC моделирует отношения, а не свойства массива. Таким образом, вы должны вызвать что-то вроде [myFactory mutableArrayValueForKey:@"widgets"], чтобы получить массив, представляющий свойство widgets.

2 голосов
/ 02 декабря 2008

Вместо того, чтобы создавать собственную блокировку, вы также можете использовать встроенную в язык блокировку:

* 1003 т.е. *

- (NSArray *)widgets {
    @synchronized(widgets)
    {
        NSArray *a = [[widgets copy] autorelease];
        return a;
    }
}

и используйте аналогичную блокировку во всех других методах доступа к widgets. (Параметр widgets, переданный в @synchronized, относится к переменной экземпляра, а не к методу.)

Комментарий Алекса о доступе к содержащимся объектам все еще применяется.

0 голосов
/ 01 декабря 2008

Вам понадобится блокировка всех методов чтения и записи. Если ваша вставка и удаление также блокируются (как вы сказали), тогда метод доступа должен быть в порядке.

...