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

1677

Что означают atomic и nonatomic в объявлениях свойств?

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

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

Теги:
atomic
properties

30 ответов

1615
Лучший ответ

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

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

С "атомарным" синтезированный сеттер/получатель гарантирует, что целое значение всегда возвращается из получателя или задается установщиком независимо от активности сеттера в любом другом потоке. То есть, если поток 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 при обновлении зависимых свойств.

  • 16
    Учитывая, что любой потокобезопасный код будет выполнять свою собственную блокировку и т. Д., Когда вы захотите использовать методы доступа к атомарным свойствам? У меня проблемы с придумыванием хорошего примера.
  • 2
    Если у вас есть средство доступа, которое будет считывать структуру (или объект) из нескольких потоков, и ваш код защищен от «действительно ли это текущее состояние», это полезно. Т.е. если вы читаете, скажем, структуру, в которой есть несколько записей, обобщающих текущее состояние, atomic может включить безопасное чтение.
Показать ещё 19 комментариев
333

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

//@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_;
    }
}

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

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

  • 8
    Не то, чтобы замок не "гарантировал безопасность нити".
  • 8
    @ Луис Гербарг: Я полагаю, что ваша версия (неатомного, сохраняющего) сеттера не будет работать должным образом, если вы попытаетесь назначить тот же объект (то есть: userName == userName_)
Показать ещё 5 комментариев
159

Atomic

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

неатомарной

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

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

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

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

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

104

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

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

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

Исполнение

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

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

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

Здесь интересная часть: Производительность с использованием доступа к атомным свойствам в неоспоримых (например, однопоточных) случаях может быть очень быстрой в некоторых случаях. В менее идеальных случаях использование атомных доступов может стоить более 20 раз над служебными данными nonatomic. В то время как аргумент Оспариваемый с использованием 7 потоков был в 44 раза медленнее для трехбайтовой структуры (2.2 GHz Core i7 Quad Core, x86_64). Трехбайтовая структура является примером очень медленного свойства.

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

Объекты в оспариваемых случаях также могут превышать 50 раз.

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

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

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

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

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

  • 0
    MRC | атомный | синтезированный геттер: 47 ARC | атомный | синтезированный геттер: 47 Что делает их одинаковыми? Разве у ARC не должно быть больше накладных расходов?
  • 2
    Так что, если атомные свойства плохие, они по умолчанию. Чтобы увеличить шаблон кода?
Показать ещё 4 комментария
96

Atomic= безопасность потока

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

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

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

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

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

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

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

Вывод atomic:

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

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

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

  • 3
    Все, что вы здесь говорите, верно, но последнее предложение, по сути, «неправильно», Дура, для сегодняшнего программирования. Это действительно невероятно, что вы попытаетесь «улучшить производительность» таким образом. (Я имею в виду, что до того, как вы доберетесь до этого через несколько лет, вы бы «не использовали ARC», «не использовали NSString, потому что он медленный!» И т. Д.) Чтобы привести крайний пример, это все равно, что сказать «команда, не помещайте никаких комментариев в код, поскольку это замедляет нас. " Не существует реалистичного конвейера разработки, где бы вы хотели (несуществующего) теоретического прироста производительности ради ненадежности.
  • 3
    @JoeBlow это факт, вы можете проверить это здесь developer.apple.com/library/mac/documentation/Cocoa/Conceptual/…
70

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

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

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

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

  • 0
    Ссылка не работает. ; (
63

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

  • atomic//По умолчанию
  • nonatomic
  • strong = retain//По умолчанию
  • weak = unsafe_unretained
  • retain
  • assign//По умолчанию
  • unsafe_unretained
  • copy
  • readonly
  • readwrite//По умолчанию

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

  • atomic

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

    Пример:

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

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

    Пример:

        @property (nonatomic, retain) NSString *name;
    
        @synthesize name;
    
  • 0
    Как можно назначить и сильный / сохранить оба по умолчанию?
  • 0
    сильный идет с ARC, сохранение было по умолчанию до ARC
52

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

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

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

  • 8
    Две причины. Во-первых, для синтезированного кода он генерирует быстрее (но не потокобезопасный код). Во-вторых, если вы пишете клиентские средства доступа, которые не являются атомарными, это позволяет вам для любого будущего пользователя отмечать, что код не является атомарным, когда они читают его интерфейс, не делая их реализацию.
50

Атомный:

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

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

-(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, он не обеспечивает полностью инициализированный возврат объекта каждый раз.

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

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

  • 5
    Этот комментарий не имеет большого смысла. Вы можете уточнить? Если вы посмотрите на примеры на сайте Apple, то ключевое слово atomic синхронизируется с объектом при обновлении его свойств.
32

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

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

15

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

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

Пример:

@property (retain) NSString *name;

@synthesize name;

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

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

Пример:

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

Объясняю:

Предположим, что существует свойство атомной строки, называемое "имя", и если вы вызываете [self setName: @ "A" ] из потока A,

Вызовите [self setName: @ "B" ] из потока B и вызовите [self name] из потока C, тогда все операции с другим потоком будут выполняться серийно, что означает, что если один поток выполняет setter или getter, тогда другие потоки будут ждать. Это делает свойство "имя" безопасным для чтения/записи, но если другой поток D вызывает [имя выпуска] одновременно, то эта операция может привести к сбою, потому что здесь нет вызова setter/getter. Это означает, что объект безопасен для чтения/записи (ATOMIC), но не является потокобезопасным, поскольку другие потоки могут одновременно отправлять сообщения любого типа в объект. Разработчик должен обеспечить безопасность потоков для таких объектов.

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

Теперь у нас есть еще несколько замечаний:

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

14

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

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

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

Обсуждение кода:

Atomic make getter и setter потока свойств безопасен. например, если u написано:

self.myProperty = value;

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

[myArray addObject:@"Abc"] 

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

  • 0
    Я не знаю, как получается последний абзац, но это просто неправильно, такого понятия, как «частная копия», не существует.
12

Нет такого ключевого слова "atomic"

@property(atomic, retain) UITextField *userName;

Мы можем использовать выше, как

@property(retain) UITextField *userName;

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

  • 10
    «Существует такое ключевое слово», что ключевое слово не требуется по умолчанию и даже является значением по умолчанию, не означает, что ключевое слово не существует.
  • 4
    Это неверно Ключевое слово существует. Этот ответ вводит в заблуждение, и я бы посоветовал снять его.
Показать ещё 1 комментарий
11

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

Пример с 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;

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

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

  • 0
    атомарный не потокобезопасный
9

atomic (по умолчанию)

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

неатомической

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

Подробнее здесь: https://realm.io/news/tmi-objective-c-property-attributes/

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

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

Как атомный по умолчанию, поэтому,

@property (retain) NSString *name;

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

self.name = @"sourov";

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

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

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

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

И

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

[self setName:@"Datta"]

из потока B,

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

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

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

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

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

То, почему атом называется thread Safe и Что называется безопасным для чтения и записи

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

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

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

- но он быстро работает

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

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

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

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

  • 4
    Как много много много maaaaany говорили другие, atomic НЕ поточно-! Он более устойчив к проблемам с потоками, но не безопасен для потоков. Это просто гарантирует, что вы получите целое значение, то есть «правильное» значение (двоичный уровень), но ни в коем случае не гарантирует, что это текущее и «правильное» значение для вашей бизнес-логики (это может быть прошлое значение и недействительным по вашей логике).
8

Прежде чем обсуждать атрибуты @property, вы должны знать, что такое использование @property. @property предлагает способ определения информации, которую класс должен инкапсулировать. Если вы объявляете объект/переменную с помощью @property, то этот объект/переменная будет доступен для других классов, импортирующих его класс. Если вы объявляете объект с использованием @property в файле заголовка, вам необходимо его синтезировать с помощью @synthesize в файле реализации.

Пример:

.h class

@interface ExampleClass : NSObject
   @property (nonatomic, retain) NSString *name;
@end

.m class

@implementation ExampleClass
   @synthesize name;
@end

Теперь компилятор будет синтезировать методы доступа для имени.

ExampleClass *newObject=[[ExampleClass alloc]init];
NSString *name1=[newObject name]; // get 'name'
[obj setName:@"Tiger"];

Список атрибутов @property: атомное. неатомический. сохранить. копия. неизменяемые. читай пиши. назначить. сильный.

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

Пример:

@property NSString *name; //by default atomic
@property (atomic)NSString *name; // explicitly declared atomic

nonatomic: он не является потокобезопасным. Вы можете использовать атрибут nonatomic property, чтобы указать, что синтезированные аксессоры просто устанавливают или возвращают значение напрямую, без каких-либо гарантий относительно того, что произойдет, если одно и то же значение будет доступно одновременно из разных потоков. По этой причине он быстрее получает доступ к неатомическому свойству, чем к атомному. @property (nonatomic)NSString *name;

Сохранить: требуется, когда атрибут является указателем на объект. Метод setter увеличит количество удержаний объекта, чтобы он занимал память в пуле автозапуска. @property (retain)NSString *name;

copy: если вы используете копию, вы не можете использовать сохранение. Использование экземпляра копии класса будет содержать свою собственную копию. Даже если измененная строка установлена ​​и впоследствии изменена, экземпляр фиксирует любое значение, которое он имеет в момент его установки. Никакие методы сеттера и геттера не будут синтезированы.

@property (copy) NSString *name;

NSMutableString *nameString = [NSMutableString stringWithString:@"Liza"];    
xyzObj.name = nameString;    
[nameString appendString:@"Pizza"];

readonly: Если вы не хотите, чтобы свойство было изменено с помощью метода setter, вы можете объявить свойство readonly. @property (readonly) NSString *name;

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

@property (readwrite) NSString *name;

assign: сгенерирует сеттер, который напрямую присваивает значение переменной экземпляра, а не копирует или сохраняет его. Это лучше всего подходит для таких примитивных типов, как NSInteger и CGFloat, или объектов, которые вы не являетесь непосредственно, например делегатов.

@property (assign) NSInteger year;

strong: это замена для сохранения. @property (nonatomic, strong) AVPlayer *player;

unsafe_unretained: Есть несколько классов в Cocoa и Cocoa Touch, которые еще не поддерживают слабые ссылки, а это означает, что вы не можете объявить слабое свойство или слабую локальную переменную, чтобы отслеживать их. Эти классы включают NSTextView, NSFont и NSColorSpace и т.д. Если вам нужно использовать слабую ссылку на один из этих классов, вы должны использовать небезопасную ссылку. Небезопасная ссылка похожа на слабую ссылку на то, что она не поддерживает связанный с ней объект, но он не будет установлен в нуль, если объект назначения будет освобожден.

@property (unsafe_unretained) NSObject *unsafeProperty;

8

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

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

7

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

Сначала прочитайте этот вопрос, а затем прочитайте ответ Bbum. Кроме того, прочитайте мое резюме.


atomic ВСЕГДА будет гарантировать

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

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

  • Atomic не гарантирует безопасность потока, хотя он полезен для обеспечения безопасности потоков. Безопасность потоков по сравнению с тем, как вы пишете свой код/​​какую очередь потоков вы читаете/пишете. Он гарантирует только многопоточность с многократной записью.

Подождите, что?! Многопоточность и безопасность потоков отличаются?

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


nonatomic

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

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

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

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

4

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

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

3

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

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

2

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

0

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

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

неатомической

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

Вежливость 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

0

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

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

0

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

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

0

Atomic

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

неатомарная

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

0

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

 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);
    }
0

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

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

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

0

Atomic: Обеспечьте безопасность потока, заблокировав поток с помощью NSLOCK.

Non atomic: не обеспечивает безопасность потока, поскольку механизм фиксации нити отсутствует.

Ещё вопросы

Сообщество Overcoder
Наверх
Меню