Блокировка переменной экземпляра в Objective-C

Каким должен быть лучший способ в приложении iOS предотвратить изменение переменной экземпляра объектом, пока другой использует ее? Должно ли быть достаточно использования директивы @synchronized(self)?

заранее спасибо


person AppsDev    schedule 13.03.2013    source источник
comment
это переменная экземпляра, а не переменная класса.. и никто не может вам достоверно сказать, учитывая только эту небольшую информацию   -  person Daij-Djan    schedule 13.03.2013
comment
Действительно ли хорошая идея редактировать вопрос (переменная класса --› переменная экземпляра), если кто-то думает, что имел в виду ОП? Из прочтения его предыдущего вопроса и ответа могло случиться так, что он действительно имел в виду переменную класса.   -  person Martin R    schedule 13.03.2013
comment
Извините, моя ошибка, я бы сказал статическая переменная, это флаг, значение которого мне нужно разделить между всеми экземплярами класса и гарантировать, что его можно изменить только экземпляром в определенное время   -  person AppsDev    schedule 13.03.2013
comment
Надеюсь, ответы ниже помогут. Я думаю, что Джастин попал в самую точку. К вашему сведению, см. также Синхронизация в Руководстве по программированию потоков.   -  person Rob    schedule 13.03.2013


Ответы (3)


Если вы хотите, чтобы объект был заблокирован, чтобы никакие два потока не использовали его одновременно, то @synchronize — это один из способов. Но это не делает его потокобезопасным.

Вы также можете использовать GCD(Grand Central Dispatch) для того же

person Anoop Vaidya    schedule 13.03.2013
comment
Я предположил, что @synchronize (или один из множества других механизмов синхронизации) использовался именно для того, чтобы сделать его потокобезопасным. Правда, если вы сделаете это неправильно, это не сработает. И да, есть более эффективные способы создания многопоточного кода (например, Советы по безопасности потоков). Но независимо от этого, можете ли вы пояснить, что @synchronize не делает его потокобезопасным? Я думал, что в этом вся цель методов синхронизации. - person Rob; 13.03.2013
comment
@Rob: Наконец-то я нашел это здесь. Также я узнал об этом в интервью :p - person Anoop Vaidya; 13.03.2013
comment
О, я пропустил вставку: p stackoverflow.com/questions/10853529/ - person Anoop Vaidya; 13.03.2013
comment
Здорово. Я на самом деле знаком с этим постом (я один из тех, кто проголосовал за него). На самом деле я думаю, что принятый ответ вводит в заблуждение по первому пункту (складка 1), касающемуся потокобезопасности, поскольку он фокусируется на использовании одного и того же токена синхронизации (ну, да). Суть в том, что я понимаю, что @synchronize может использоваться для обеспечения безопасности потоков, хотя, как свидетельствует этот пост (и моя ссылка выше), есть лучшие способы сделать это. Это не похоже на распространенное заблуждение, что atomic обеспечивает безопасность потоков (а это не так). @synchronize можно, но есть и лучшие способы. Семантика, наверное. - person Rob; 13.03.2013
comment
да, я согласен с вами, для атомарного я разместил вопрос stackoverflow.com/questions/12347236/ :) - person Anoop Vaidya; 13.03.2013

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

Старый добрый замок, например pthread_mutex; вы также можете использовать оболочку Objective-C для этого (например, NSLock и NSRecursiveLock). @synchronized также попадает в эту категорию, но это механизм самого высокого уровня, упомянутый здесь.

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

К сожалению, в этой области очень не хватает чистых ObjC/Cocoa - разработка высокоэффективной параллельной программы с использованием только технологий ObjC и Cocoa намного сложнее, чем должна быть (или должна быть).

Должно ли быть достаточно использования директивы @synchronized(self)?

Для простых случаев этого вполне достаточно. Это объектный уровень Recursive Lock.

Однако это довольно медленно по сравнению с другими вариантами взаимного исключения.

Я не думаю, что @synchronized имеет для этого большое значение, кроме:

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

@synchronized удобен, но поскольку он имеет высокую стоимость, его следует использовать с осторожностью.

person justin    schedule 13.03.2013

Если единственная цель состоит в том, чтобы иметь возможность получить доступ

self.myString; //getter

а также,

self.myString=aString; //setter

Лучше всего объявить его атомарным, например:

@property (atomic, strong) NSString* myString;

Это гарантирует, что в многопоточной среде установка и получение myString потоком 1 защищены от действий потока 2.

person Khaled Barazi    schedule 13.03.2013