В чем разница между атомарными и неатомными атрибутами?

StackOverflow https://stackoverflow.com/questions/588866

Вопрос

Что делать atomic и nonatomic что имеется в виду в декларациях о собственности?

@property(nonatomic, retain) UITextField *userName;
@property(atomic, retain) UITextField *userName;
@property(retain) UITextField *userName;

В чем оперативная разница между этими тремя?

Это было полезно?

Решение

Последние два варианта идентичны;"атомарный" - это поведение по умолчанию (обратите внимание, что на самом деле это не ключевое слово;это определяется только отсутствием nonatomic -- atomic было добавлено в качестве ключевого слова в последних версиях llvm /clang).

Предполагая, что вы @синтезируете реализации метода, atomic противнеатомный изменяет сгенерированный код.Если вы пишете свой собственный сеттер / геттеры, atomic / nonatomic / retain / assign / copy являются просто рекомендательными.(Примечание:@synthesize теперь используется по умолчанию в последних версиях LLVM.Также нет необходимости объявлять переменные экземпляра;они также будут синтезированы автоматически и будут иметь _ добавляется к их названию для предотвращения случайного прямого доступа).

С помощью "atomic" синтезированный установщик / получатель гарантирует, что весь значение всегда возвращается из средства получения или устанавливается установщиком, независимо от активности установщика в любом другом потоке.То есть, если поток A находится в середине средства получения, в то время как поток B вызывает средство установки, фактическое жизнеспособное значение - скорее всего, автоматически выпущенный объект - будет возвращено вызывающей стороне в A.

В nonatomic, никаких таких гарантий не дается.Таким образом, nonatomic значительно быстрее, чем "атомный".

Что делает "атомный" нет сделать это - дать какие-либо гарантии потокобезопасности.Если поток A вызывает средство получения одновременно с потоками B и C, вызывающими средство установки с разными значениями, поток A может получить любое из трех возвращаемых значений - то, которое предшествовало вызову любых средств установки, или любое из значений, переданных в средства установки в B и C.Аналогично, объект может в конечном итоге получить значение из B или C, определить это невозможно.

Обеспечение целостности данных - одна из основных задач многопоточного программирования - достигается другими средствами.

Добавление к этому:

atomicity использование одного свойства также не может гарантировать потокобезопасность, когда задействовано несколько зависимых свойств.

Рассмотреть:

 @property(atomic, copy) NSString *firstName;
 @property(atomic, copy) NSString *lastName;
 @property(readonly, atomic, copy) NSString *fullName;

В этом случае поток A может переименовывать объект, вызывая setFirstName: а потом звонит setLastName:.В то же время поток B может вызвать fullName в промежутке между двумя вызовами поток A и получит новое имя в сочетании со старой фамилией.

Чтобы решить эту проблему, вам нужен транзакционная модель.То есть.некоторый другой вид синхронизации и / или исключения, который позволяет исключить доступ к fullName в то время как зависимые свойства обновляются.

Другие советы

Это объясняется в руководстве Apple Документация, но ниже приведены некоторые примеры того, что происходит на самом деле.Обратите внимание, что нет ключевого слова "atomic", если вы не укажете "nonatomic", то свойство будет атомарным, но явное указание "atomic" приведет к ошибке.

//@property(nonatomic, retain) UITextField *userName;
//Generates roughly

- (UITextField *) userName {
    return userName;
}

- (void) setUserName:(UITextField *)userName_ {
    [userName_ retain];
    [userName release];
    userName = userName_;
}

Теперь атомарный вариант немного сложнее:

//@property(retain) UITextField *userName;
//Generates roughly

- (UITextField *) userName {
    UITextField *retval = nil;
    @synchronized(self) {
        retval = [[userName retain] autorelease];
    }
    return retval;
}

- (void) setUserName:(UITextField *)userName_ {
    @synchronized(self) {
      [userName_ retain];
      [userName release];
      userName = userName_;
    }
}

По сути, атомарная версия должна принимать блокировку, чтобы гарантировать потокобезопасность, а также увеличивает количество ссылок на объект (и количество авторелизов, чтобы сбалансировать его), чтобы объект гарантированно существовал для вызывающей стороны, в противном случае существует потенциальное условие гонки, если другой поток устанавливает значение, в результате чего количество ссылок падает до 0.

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

Атомный

  • это поведение по умолчанию
  • гарантирует, что текущий процесс будет завершен центральным процессором, прежде чем другой процесс обратится к переменной
  • это не быстро, так как гарантирует полное завершение процесса

Неатомный

  • это НЕ поведение по умолчанию
  • быстрее (для синтезированного кода, то есть для переменных, созданных с помощью @property и @synthesize)
  • не потокобезопасен
  • может привести к неожиданному поведению, когда два разных процесса обращаются к одной и той же переменной одновременно

Лучший способ понять разницу - использовать следующий пример.

Предположим, существует атомарное строковое свойство с именем "name", и если вы вызываете [self setName:@"A"] из потока A вызовите [self setName:@"B"] из потока B и вызовите [self name] начиная с потока C, все операции в разных потоках будут выполняться последовательно, что означает, что если один поток выполняет установщик или получатель, то другие потоки будут ждать.

Это делает чтение / запись свойства "name" безопасной, но если другой поток, D, вызывает [name release] одновременно эта операция может привести к сбою, потому что здесь не задействован вызов setter / getter.Это означает, что объект безопасен для чтения / записи (АТОМАРНЫЙ), но не потокобезопасен, поскольку другие потоки могут одновременно отправлять объекту сообщения любого типа.Разработчик должен обеспечить потокобезопасность для таких объектов.

Если свойство "name" было неатомным, то все потоки в приведенном выше примере - A, B, C и D будут выполняться одновременно, что приведет к любому непредсказуемому результату.В случае atomic либо один из A, B или C будет выполняться первым, но D все равно может выполняться параллельно.

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

В чем функциональная разница между этими тремя?

Я всегда считал atomic довольно любопытным по умолчанию.На уровне абстракции мы работаем над использованием атомарных свойств для класса в качестве средства достижения 100% потокобезопасности.Для действительно корректных многопоточных программ почти наверняка требуется вмешательство программиста.Между тем, эксплуатационные характеристики и исполнение еще не были подробно описаны.Написав за эти годы несколько сильно многопоточных программ, я объявлял свои свойства как nonatomic все это время, потому что atomic не был разумным ни для каких целей.Во время обсуждения деталей атомных и неатомных свойств этот вопрос, Я провел некоторое профилирование и получил некоторые любопытные результаты.

Исполнение

ОК.Первое, что я хотел бы прояснить, это то, что реализация блокировки определяется реализацией и абстрагируется.Луи использует @synchronized(self) в его примере я рассматривал это как распространенный источник путаницы.Реализация не приводит к на самом деле использование @synchronized(self);он использует объектный уровень вращающиеся замки.Иллюстрация Луиса хороша для иллюстрации высокого уровня с использованием конструкций, с которыми мы все знакомы, но важно знать, что она не использует @synchronized(self).

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

Производительность

Вот самая интересная часть:Производительность при использовании доступа к атомарным свойствам в неоспоримый (например,однопоточные) случаи в некоторых случаях могут быть действительно очень быстрыми.В далеко не идеальных случаях использование атомарного доступа может обойтись более чем в 20 раз дороже, чем nonatomic.В то время как Оспариваемый случай с использованием 7 потоков был в 44 раза медленнее для трехбайтовой структуры (2,2 ГГц Ядро i7 Четырехъядерный процессор, x86_64).Трехбайтовая структура является примером очень медленного свойства.

Интересное побочное замечание:Определяемые пользователем средства доступа к трехбайтовой структуре были в 52 раза быстрее, чем синтезированные атомарные средства доступа;или на 84% выше скорости синтезированных неатомных средств доступа.

Количество возражений в оспариваемых случаях также может превышать 50 раз.

Из-за большого количества оптимизаций и вариаций в реализациях довольно сложно измерить реальное воздействие в этих контекстах.Вы часто можете услышать что-то вроде "Доверяйте этому, если только вы не составите профиль и не обнаружите, что это проблема".Из-за уровня абстракции на самом деле довольно сложно измерить фактическое воздействие.Получение фактических затрат из профилей может занять очень много времени и из-за абстракции быть довольно неточным.Кроме того, ARC против MRC может иметь большое значение.

Так что давайте сделаем шаг назад, нет сосредоточившись на реализации доступа к собственности, мы включим обычные подозреваемые, такие как objc_msgSend, и изучите некоторые реальные результаты высокого уровня для многих обращений к NSString добытчик в неоспоримый случаи (значения в секундах):

  • MRC | неатомные | реализованные вручную геттеры:2
  • MRC | неатомный | синтезированный геттер:7
  • MRC | атомарный | синтезированный геттер:47
  • ДУГОВОЙ | неатомный | синтезированный геттер:38 (примечание:ARC добавляет циклическое количество ссылок здесь)
  • ДУГОВОЙ | атомарный | синтезированный геттер:47

Как вы, наверное, догадались, активность / цикличность подсчета ссылок вносит значительный вклад в atomics и under ARC.Вы также увидели бы большие различия в оспариваемых делах.

Хотя я уделяю пристальное внимание производительности, я все же говорю Сначала семантика!.Между тем, производительность является низким приоритетом для многих проектов.Однако знание деталей выполнения и стоимости используемых вами технологий, безусловно, не повредит.Вы должны использовать правильную технологию, соответствующую вашим потребностям, целям и способностям.Надеюсь, это сэкономит вам несколько часов на сравнениях и поможет принять более обоснованное решение при разработке ваших программ.

Атомный = безопасность резьбы

Неатомный = Нет потокобезопасности

Безопасность резьбы:

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

В нашем контексте:

Если поток изменяет значение экземпляра, измененное значение доступно всем потокам, и только один поток может изменять значение одновременно.

Где использовать atomic:

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

Последствия atomic:

Не так быстро , как nonatomic потому что nonatomic для этого не требуется никакой работы сторожевого таймера во время выполнения.

Где использовать nonatomic:

Если переменная экземпляра не будет изменяться несколькими потоками, вы можете использовать ее.Это повышает производительность.

Я нашел довольно хорошо изложенное объяснение атомных и неатомных свойств здесь.Вот несколько соответствующих текстов из того же:

"атомный" означает, что он не может быть расщеплен.В терминах операционной системы / программирования атомарный вызов функции - это вызов, который не может быть прерван - вся функция должна быть выполнена, а не выгружена из процессора обычным переключением контекста ОС до ее завершения.Просто на случай, если ты не знал:поскольку центральный процессор может выполнять только одно действие одновременно, операционная система распределяет доступ к центральному процессору для всех запущенных процессов небольшими временными интервалами, чтобы иллюзия о многозадачности.Планировщик процессора может (и делает) прервать процесс в любой момент его выполнения - даже в середине вызова функции.Таким образом, для таких действий, как обновление общих переменных счетчика, когда два процесса могут попытаться обновить переменную одновременно, они должны выполняться "атомарно", т. е. каждое действие обновления должно завершиться полностью, прежде чем любой другой процесс сможет быть переключен на центральный процессор.

Итак, я бы предположил, что atomic в данном случае означает, что методы чтения атрибутов не могут быть прерваны - по сути, это означает, что переменные, считываемые методом, не могут изменить свое значение на полпути, потому что какой-то другой поток / вызов / функция заменяется на CPU.

Потому что atomic переменные не могут быть прерваны, значение, содержащееся в них в любой точке (thread-lock), гарантированно будет некоррумпированный, хотя обеспечение блокировки этого потока замедляет доступ к ним. non-atomic переменные, с другой стороны, не дают такой гарантии, но предлагают роскошь более быстрого доступа.Подводя итог, пойдите с non-atomic когда вы знаете, что ваши переменные не будут доступны нескольким потокам одновременно, это ускоряет процесс.

Прочитав так много статей, сообщений о переполнении стека и создав демонстрационные приложения для проверки атрибутов свойств переменных, я решил собрать всю информацию об атрибутах воедино:

  1. atomic // По умолчанию
  2. nonatomic
  3. strong = retain // По умолчанию
  4. weak = unsafe_unretained
  5. retain
  6. assign // По умолчанию
  7. unsafe_unretained
  8. copy
  9. readonly
  10. readwrite // По умолчанию

В статье Атрибуты или модификаторы переменных свойств в iOS вы можете найти все вышеперечисленные атрибуты, и это определенно поможет вам.

  1. atomic

    • atomic означает, что только один поток имеет доступ к переменной (статический тип).
    • atomic является потокобезопасным.
    • Но это низкая производительность
    • atomic это поведение по умолчанию
    • Атомарные средства доступа в среде, не собирающей мусор (т. е.при использовании retain / release / autorelease) будет использовать блокировку, чтобы гарантировать, что другой поток не помешает правильной настройке / получению значения.
    • На самом деле это не ключевое слово.

    Пример:

        @property (retain) NSString *name;
    
        @synthesize name;
    
  2. nonatomic

    • nonatomic означает, что несколько потоков обращаются к переменной (динамический тип).
    • nonatomic небезопасен для потоков.
    • Но он быстр в исполнении
    • nonatomic это НЕ поведение по умолчанию.Нам нужно добавить nonatomic ключевое слово в атрибуте свойства.
    • Это может привести к неожиданному поведению, когда два разных процесса (потока) обращаются к одной и той же переменной одновременно.

    Пример:

        @property (nonatomic, retain) NSString *name;
    
        @synthesize name;
    

Атомный :

Atomic гарантирует, что доступ к свойству будет осуществляться атомарным способом.Например.он всегда возвращает полностью инициализированные объекты, любое получение / набор свойства в одном потоке должно завершиться, прежде чем другой сможет получить к нему доступ.

Если вы представите себе следующую функцию, выполняемую в двух потоках одновременно, вы сможете понять, почему результаты были бы некрасивыми.

-(void) setName:(NSString*)string
{
  if (name)
  {
    [name release]; 
    // what happens if the second thread jumps in now !?
    // name may be deleted, but our 'name' variable is still set!
    name = nil;
  }

  ...
}

Плюсы : Возврат полностью инициализированных объектов каждый раз делает его лучшим выбором в случае многопоточности.

Минусы : Снижение производительности, немного замедляющее выполнение

Неатомный :

В отличие от Atomic, он не гарантирует каждый раз возврата полностью инициализированного объекта.

Плюсы : Чрезвычайно быстрое выполнение.

Минусы : Вероятность получения мусорного значения в случае многопоточности.

Сначала самый простой ответ:Между вашими двумя вторыми примерами нет никакой разницы.По умолчанию средства доступа к свойствам являются атомарными.

Атомарные средства доступа в среде, не собирающей мусор (т. е.при использовании retain / release / autorelease) будет использовать блокировку, чтобы гарантировать, что другой поток не помешает правильной настройке / получению значения.

Посмотрите на "Производительность и многопоточность" раздел документации Apple Objective-C 2.0 для получения дополнительной информации и для других соображений при создании многопоточных приложений.

Атомарный означает, что только один поток обращается к переменной (статический тип).Atomic потокобезопасен, но работает медленно.

Неатомный означает, что несколько потоков обращаются к переменной (динамический тип).Nonatomic небезопасен для потоков, но он быстр.

Атомный - это резьбонадежный, это медленно и это надежность (не гарантируется) что предоставляется только заблокированное значение независимо от того, сколько потоков пытаются получить доступ через одну и ту же зону.При использовании atomic фрагмент кода, написанный внутри этой функции, становится частью критической секции, к которой одновременно может выполняться только один поток.

Это только гарантирует потокобезопасность;это не гарантирует этого. Я имею в виду, что вы нанимаете опытного водителя для своей машины, но это все равно не гарантирует, что машина не попадет в аварию.Однако вероятность остается малейшей.

Атомарный - он не может быть расщеплен, так что результат ожидаем.С неатомным - когда другой поток обращается к зоне памяти, он может изменить ее, поэтому результат получается неожиданным.

Разговор о коде :

Atomic делает метод получения и настройки свойства потокобезопасным.например, если вы написали :

self.myProperty = value;

является потокобезопасным.

[myArray addObject:@"Abc"] 

НЕ ЯВЛЯЕТСЯ потокобезопасным.

Такого ключевого слова "atomic" не существует

@property(atomic, retain) UITextField *userName;

Мы можем использовать вышеприведенное следующим образом

@property(retain) UITextField *userName;

Смотрите вопрос о переполнении стека У меня возникают проблемы, если я использую @property(атомарный, сохранить)NSString *myString.

Тот Самый По умолчанию является atomic, это означает, что это действительно снижает вашу производительность всякий раз, когда вы используете свойство, но оно потокобезопасно.Что делает Objective-C, так это устанавливает блокировку, поэтому только фактический поток может получить доступ к переменной, пока выполняется установщик / получатель.

Пример с MRC свойства с ivar _internal:

[_internal lock]; //lock
id result = [[value retain] autorelease];
[_internal unlock];
return result;

Итак, эти последние два - одно и то же:

@property(atomic, retain) UITextField *userName;

@property(retain) UITextField *userName; // defaults to atomic

С другой стороны, делает nonatomic ничего не добавляйте в свой код.Таким образом, это потокобезопасно только в том случае, если вы сами кодируете механизм безопасности.

@property(nonatomic, retain) UITextField *userName;

Ключевые слова вообще не обязательно должны быть записаны как атрибут first property.

Не забывайте, это не означает, что свойство в целом потокобезопасно.Есть только вызов метода установщика / добытчика.Но если вы используете сеттер, а затем геттер одновременно с двумя разными потоками, это тоже может быть сломано!

атомарный (по умолчанию)

По умолчанию используется Atomic:если вы ничего не вводите, ваше свойство является атомарным.Атомарное свойство гарантирует, что при попытке чтения из него вы получите обратно допустимое значение.Это не дает никаких гарантий относительно того, каким может быть это значение, но вы получите обратно хорошие данные, а не просто ненужную память.Что это позволяет вам сделать, так это если у вас есть несколько потоков или несколько процессов, указывающих на одну переменную, один поток может читать, а другой поток может записывать.Если они совпадают в одно и то же время, поток чтения гарантированно получит одно из двух значений:либо до изменения, либо после изменения.Чего atomic не дает вам, так это какой-либо гарантии относительно того, какое из этих значений вы можете получить.Atomic действительно часто путают с потокобезопасностью, и это неверно.Вам необходимо гарантировать потокобезопасность другими способами.Однако atomic гарантирует, что если вы попытаетесь прочитать, вы получите обратно какое-то значение.

неатомный

С другой стороны, неатомный, как вы, вероятно, можете догадаться, просто означает: “не делай этого атомарного”. То, что ты теряешь, - это гарантию того, что ты всегда что-то получаешь взамен.Если вы попытаетесь прочитать в середине записи, вы можете получить обратно мусорные данные.Но, с другой стороны, вы идете немного быстрее.Поскольку атомарные свойства должны творить какую-то магию чтобы гарантировать, что вы получите обратно значение, они работают немного медленнее.Если это свойство, к которому вы часто обращаетесь, вы можете захотеть перейти к nonatomic, чтобы убедиться, что вы не увеличиваете скорость штрафа.

Смотрите больше здесь: https://realm.io/news/tmi-objective-c-property-attributes/

Если вы используете свое свойство в многопоточном коде, то вы сможете увидеть разницу между неатомными и атомарными атрибутами.Неатомный работает быстрее атомарного, а атомарный потокобезопасен, но не неатомный.

Виджайендра Трипати уже приводил пример для многопоточной среды.

  • -Атомарный означает, что только один поток имеет доступ к переменной (статический тип).
  • -Atomic потокобезопасен.
  • -но это медленная работа

Как объявить:

Поскольку atomic используется по умолчанию, поэтому,

@property (retain) NSString *name;

И в файле реализации

self.name = @"sourov";

Предположим, что задача, связанная с тремя свойствами, является

 @property (retain) NSString *name;
 @property (retain) NSString *A;
 @property (retain) NSString *B;
 self.name = @"sourov";

Все свойства работают параллельно (например, асинхронно).

Если вы вызываете "name" из потока A,

И

В то же время, если вы позвоните

[self setName:@"Datta"]

из потока B,

Теперь, если свойство *name является неатомным тогда

  • Он вернет значение "Datta" для
  • Он вернет значение "Datta" для B

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

Теперь, если свойство *name является атомарным

  • Это обеспечит ценность "Сурова" для
  • Затем он вернет значение "Datta" для B

Вот почему atomic называется потокобезопасным и Вот почему он называется безопасным для чтения и записи

В такой ситуации операцию будут выполнять последовательно. И медленный в производительности

- Неатомный означает множественный доступ потоков к переменной (динамический тип).

- Неатомный поток небезопасен.

- но он быстр в исполнении

-Nonatomic НЕ является поведением по умолчанию, нам нужно добавить ключевое слово nonatomic в атрибут property.

For В Swift Подтверждение того, что свойства Swift неатомичны в смысле ObjC.Одна из причин заключается в том, что вы задумываетесь о том, достаточна ли атомарность для каждого свойства для ваших нужд.

Ссылка: https://forums.developer.apple.com/thread/25642

Для получения дополнительной информации, пожалуйста, посетите веб-сайт http://rdcworld-iphone .blogspot.in/2012/12/variable-property-attributes-or.html

Прежде чем вы начнете:Вы должны знать, что каждый объект в памяти должен быть освобожден из памяти, чтобы появилась новая запись.Вы не можете просто писать поверх чего-то, как вы делаете это на бумаге.Ты должен сначала сотрите (освободите) его, а затем вы можете писать на нем.Если на данный момент стирание завершено (или наполовину завершено) и ничего не еще не сделал было написано (или наполовину написано), и вы пытаетесь это прочитать, что может быть очень проблематично!Атомарные и неатомные методы помогут вам решить эту проблему по-разному.

Первое прочтение это задайте вопрос, а затем прочитайте Ответ Bbum'а.Кроме того, тогда прочтите мое резюме.


atomic всегда будет гарантировать

  • Если два разных человека захотят читать и писать одновременно, ваша бумага просто так не сгорит!--> Ваше приложение никогда не выйдет из строя, даже в состоянии гонки.
  • Если один человек пытается писать и написал только 4 из 8 букв, которые нужно написать, то никто не сможет прочитать середину, чтение может быть выполнено только тогда, когда будут написаны все 8 букв -> Никакое чтение (get) не произойдет в "потоке, который все еще пишет", т.е.если необходимо записать 8 байт в байт, а записано только 4 байта - до этого момента вам не разрешается читать из него.Но поскольку я сказал, что он не рухнет, то он будет считываться из значения an автоматически выпущенный объект.
  • Если до того, как пишу тебе иметь стер то, что было ранее написано на бумаге, и тогда кто-то захочет тебя прочесть может все еще читаю.Каким образом?Вы будете читать из чего-то похожего на корзину Mac OS (поскольку корзина для мусора еще не удалена на 100%...она находится в подвешенном состоянии) ---> Если ThreadA должна считываться, в то время как ThreadB уже освобожден для записи, вы получите значение либо из окончательного полностью записанного значения ThreadB, либо получите что-то из пула автоматического выпуска.

Количество сохранений - это способ управления памятью в Objective-C.Когда вы создаете объект, его количество сохранений равно 1.Когда вы отправляете объекту сообщение о сохранении, его количество сохранений увеличивается на 1.Когда вы отправляете объекту сообщение об освобождении, количество его сохранений уменьшается на 1.Когда вы отправляете объект, сообщение об автоматическом выпуске, его количество сохранений уменьшается на 1 на некотором этапе в будущем.Если object's сохранить подсчет сводится к 0, он будет освобожден.

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

Что?!Являются многопоточными и безопасность резьбы другой?

ДА.Многопоточность означает:несколько потоков могут одновременно считывать общий фрагмент данных, и мы не допустим сбоя, но это не гарантирует, что вы не читаете из значения, не являющегося автоматически выпущенным.Благодаря потокобезопасности гарантируется, что то, что вы читаете, не будет автоматически выпущено.Причина, по которой мы не делаем все атомарным по умолчанию, заключается в том, что существуют затраты на производительность, и для большинства вещей на самом деле не нужна потокобезопасность.Это необходимо нескольким частям нашего кода, и для этих нескольких частей нам нужно написать наш код потокобезопасным способом, используя блокировки, мьютекс или синхронизацию.


nonatomic

  • Поскольку не существует такой вещи, как корзина для мусора Mac OS, то никого не волнует, всегда ли вы получаете значение (<-- Это потенциально может привести к сбою), и никого не волнует, если кто-то попытается прочитать половину написанного вами (хотя наполовину написанное в памяти сильно отличается от наполовину написанного на бумаге, в памяти это может дать вам безумно глупое значение из предыдущего, в то время как на бумаге вы видите только половину того, что было написано) -> Не гарантирует, что не произойдет сбой, потому что он не использует механизм автоматического выпуска.
  • Не гарантирует, что все записанные значения будут прочитаны!
  • Быстрее, чем атомарный

В целом они отличаются в двух аспектах:

  • Сбой или нет из-за наличия или отсутствия пула авторелиза.

  • Разрешать чтение прямо в середине "еще не законченной записи или пустого значения" или не разрешать и разрешать чтение только тогда, когда значение равно полностью написано.

Атомарное свойство гарантирует сохранение полностью инициализированного значения независимо от того, сколько потоков выполняет над ним getter & setter.

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

Атомарный означает, что только один поток может получить доступ к переменной одновременно (статический тип).Atomic потокобезопасен, но работает медленно.

Неатомный означает, что несколько потоков могут обращаться к переменной одновременно (динамический тип).Nonatomic небезопасен для потоков, но он быстр.

Атомарность атомарный (по умолчанию)

По умолчанию используется Atomic:если вы ничего не вводите, ваше свойство является атомарным.Атомарное свойство гарантирует, что при попытке чтения из него вы получите обратно допустимое значение.Это не дает никаких гарантий относительно того, каким может быть это значение, но вы получите обратно хорошие данные, а не просто ненужную память.Что это позволяет вам сделать, так это если у вас есть несколько потоков или несколько процессов, указывающих на одну переменную, один поток может читать, а другой поток может записывать.Если они совпадают в одно и то же время, поток чтения гарантированно получит одно из двух значений:либо до изменения, либо после изменения.Чего atomic не дает вам, так это какой-либо гарантии относительно того, какое из этих значений вы можете получить.Atomic действительно часто путают с потокобезопасностью, и это неверно.Вам необходимо гарантировать потокобезопасность другими способами.Однако atomic гарантирует, что если вы попытаетесь прочитать, вы получите обратно какое-то значение.

неатомный

С другой стороны, неатомный, как вы, вероятно, можете догадаться, просто означает: “не делай этого атомарного”. То, что ты теряешь, - это гарантию того, что ты всегда что-то получаешь взамен.Если вы попытаетесь прочитать в середине записи, вы можете получить обратно мусорные данные.Но, с другой стороны, вы идете немного быстрее.Поскольку атомарные свойства должны творить какую-то магию чтобы гарантировать, что вы получите обратно значение, они работают немного медленнее.Если это свойство, к которому вы часто обращаетесь, вы можете захотеть перейти к nonatomic, чтобы убедиться, что вы не увеличиваете скорость штрафа.Доступ

вежливость https://academy.realm.io/posts/tmi-objective-c-property-attributes/

Атрибуты свойства атомарности (атомарные и неатомные) не отражены в соответствующем объявлении свойства Swift, но гарантии атомарности реализации Objective-C остаются в силе при доступе к импортированному свойству из Swift.

Итак, если вы определите атомарное свойство в Objective-C, оно останется атомарным при использовании Swift.

вежливость https://medium.com/@YogevSitton/atomic-vs-non-atomic-properties-crash-course-d11c23f4366c

Если вы используете atomic, это означает, что поток будет безопасным и доступным только для чтения.Если вы используете неатомный, это означает, что несколько потоков обращаются к переменной и это небезопасно для потоков, но выполняется быстро, выполняются операции чтения и записи;это динамический тип.

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

 static inline void reallySetProperty(id self, SEL _cmd, id newValue, 
      ptrdiff_t offset, bool atomic, bool copy, bool mutableCopy) 
    {
        id oldValue;
        id *slot = (id*) ((char*)self + offset);

        if (copy) {
            newValue = [newValue copyWithZone:NULL];
        } else if (mutableCopy) {
            newValue = [newValue mutableCopyWithZone:NULL];
        } else {
            if (*slot == newValue) return;
            newValue = objc_retain(newValue);
        }

        if (!atomic) {
            oldValue = *slot;
            *slot = newValue;
        } else {
            spin_lock_t *slotlock = &PropertyLocks[GOODHASH(slot)];
            _spin_lock(slotlock);
            oldValue = *slot;
            *slot = newValue;        
            _spin_unlock(slotlock);
        }

        objc_release(oldValue);
    }

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

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

Чтобы упростить всю путаницу, давайте разберемся с блокировкой мьютекса.

Блокировка мьютекса, согласно названию, блокирует изменчивость объекта.Таким образом, если доступ к объекту осуществляется классом, ни один другой класс не может получить доступ к тому же объекту.

В iOS, @sychronise также обеспечивает блокировку мьютекса .Теперь он работает в режиме FIFO и гарантирует, что на поток не влияют два класса, совместно использующие один и тот же экземпляр.Однако, если задача находится в основном потоке, избегайте доступа к объекту с использованием атомарных свойств, поскольку это может задержать ваш пользовательский интерфейс и снизить производительность.

Атомный:Обеспечьте безопасность потока, зафиксировав поток с помощью NSLOCK.

Неатомный:Не обеспечивает потокобезопасность, так как отсутствует механизм блокировки потока.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top