2016-11-09 2 views
2

У меня есть объект со свойством:Действительно ли это поточно-безопасное чтение переменной экземпляра при вызове сеттера из другого потока?

@interface Car 
@property(strong) NSLicensePlate *licensePlate; 
@end 

я использую свойство в способе:

- (void) doSomething { 
    [_licensePlate frobnicate]; 
} 

И значения свойства могут быть изменены в другом методе:

- (void) doSomethingElse { 
    [self setLicensePlate:[_licensePlateDealer cleanLicensePlate]]; 
} 

Теперь, если метод -doSomethingElse вызывается из другого потока, когда я обращаюсь к свойству номерной знак с использованием переменной экземпляра (как видно из -doSomething), можно ли получить segfault?

Возможно ли, что установщик -setLicensePlate освобождает значение, хранящееся в _licensePlate, до того, как я назову на него -frobnicate и до того, как будет присвоено новое допустимое значение? И поможет ли это позвонить [self licensePlate], а не использовать _licensePlate?

+1

@bbum - Я понимаю, почему вы отметили это как обман, но это не совсем (или не на этот вопрос, по крайней мере), потому что (а) он не спрашивает, что такое атомарность, а может ли вы наслаждаться этим, если вы использовать ивар; и (б) он спрашивает о жизненном цикле объекта, который может запускать метод, когда свойство установлено на другой объект в другом потоке. – Rob

ответ

3

Если вы хотите, чтобы насладиться atomic поведением (что является поведением по умолчанию, что вы получаете, потому что вы не указали nonatomic спецификатора) этого имущества, вы должны использовать геттер (self.licensePlate или [self licensePlate]), не используйте ivar (_licensePlate).

В общем, обычно разумно использовать геттеры и сеттеры везде, кроме (а) метода init; и (б) и методы пользовательского доступа. Накладные расходы незначительны, и вы избегаете спектра потенциальных проблем: от атомарности, семантики памяти, KVO, кода будущей проверки, если вы настроите методы доступа в будущем в будущем и т. Д.

Но, если вы получите доступ к своей собственности только через методы аксессоров (методы получения и установка), то atomic классификатор, как описано Programming with Objective-C: Encapsulating Data гарантирует, что указатель, сам, что вы запрашиваете/установка не будет повреждена другим поток:

[Atomic] означает что синтезированные аксессоры гарантируют, что значение всегда полностью извлекается методом геттера или полностью устанавливается с помощью метода setter, даже если аксессоры называются одновременными из разных потоков.

В ответ на ваш вопрос, если другой поток изменяет licensePlate свойства, в то время как метод frobnicate работает на другом потоке, что исходный объект будет не будет выпущен до тех пор, как этот метод возвращает.

Но, чтобы быть ясным, atomic квалификатор не обеспечить безопасность потока. Как выше руководство идет на нас предупредить:

Примечание: атомарность недвижимости не является синонимом безопасности потока объекта.

Рассмотрите объект XYZPerson, в котором оба имени и фамилии человека изменяются с использованием атомарных аксессуаров из одного потока. Если другой поток обращается к обоим именам одновременно, атомарные методы getter возвратят полные строки (без сбоев), но нет никакой гарантии, что эти значения будут правильными именами относительно друг друга. Если перед изменением открывается первое имя, но после изменения выдается последнее имя, вы получите несогласованную, несогласованную пару имен.

Этот пример довольно прост, но проблема безопасности потоков значительно усложняется при рассмотрении по сети связанных объектов. Защита резьбы более подробно освещена в Concurrency Programming Guide.

Таким образом, может поточно-использовать frobnicate в одном потоке, делая другие вещи в другом потоке, но он также не может. Это зависит от всех вещей, которые могут быть сделаны с этим объектом номерного знака. Поскольку защита, предлагаемая atomic, настолько минималистична, мы часто используем некоторую синхронизацию (через последовательную очередь GCD или шаблон считывателя GCD или с помощью любого из методов синхронизации, описанных в Threading Programming Guide: Synchronization, таких как блокировки) для координации взаимодействия с различными потоками.

0

При определении свойств вы можете установить их как atomic (по умолчанию) или nonatomic.

Поскольку вы используете atomic по умолчанию, вы должны быть хорошо о безопасности потока, но это также зависит от того, как вы реализовали frobnicate, setLicensePlate: и cleanLicensePlate.

Пожалуйста, обратитесь к этому вопросу, чтобы получить более подробную информацию о atomic против nonatomic: What's the difference between the atomic and nonatomic attributes?