Питання Яка різниця між атомними та неатомними атрибутами?


Що робити atomic і nonatomic означає в деклараціях про майно?

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

Яка операційна різниця між цими трьома?


1723
2018-02-26 02:31


походження


developer.apple.com/library/mac/#documentation/Cocoa/Conceptual/... - KKendall
@ Alex Wayne - у мене є одна проблема, і я опублікував це, але ніхто не відповідав на це. Так що ви можете допомогти мені за це. Посилання на запитання - stackoverflow.com/questions/35769368/... - DJ1


Відповіді:


Останні два ідентичні; "атомний" - поведінка за умовчанням (Зауважте, що насправді це не ключове слово; воно вказується лише відсутністю nonatomic - atomic був доданий як ключове слово в останніх версіях lvvm / clang).

Припускаючи, що ви @ синтезуєте реалізацію методу, атомний або неатомний змінює сформований код. Якщо ви пишете власний сеттер / геттер, атомний / nonatomic / save / assign / copy є просто консультативним. (Примітка: @ synthesize тепер є поведінкою за умовчанням в останніх версіях LLVM, також не потрібно оголошувати змінні екземплярів, вони також будуть синтезовані автоматично, і матимуть _ додано до їх імені, щоб уникнути випадкового прямого доступу).

З "атомним" синтезований сеттер / геттер забезпечить, щоб a цілий значення завжди повертається від геттера або встановлюється встановлювачем, незалежно від активності setter на будь-якій іншій гілці. Тобто, якщо нитка А знаходиться посередині геттера, а нитка B називає встановлювач, фактична життєдайна цінність - об'єкт, що виділяється автором, найімовірніше, буде повернутись абоненту в А.

В 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 а залежні властивості оновлюються.


1668
2018-02-26 06:40



Враховуючи, що будь-який код, який працює з потоками, буде робити власний замок і т. Д., Коли б ви хотіли використовувати атомні властивості? Мені непогано думати про хороший приклад. - Daniel Dickison
@bbum має сенс Мені подобається ваш коментар до іншої відповіді, що безпека потоків - це більше стурбованість на рівні моделі. З визначення безпеки IBM потоку: ibm.co/yTEbjY "Якщо клас правильно реалізований, що є іншим способом сказати, що він відповідає його специфікації, жодна послідовність операцій (читає або записує публічні поля та дзвінки на загальнодоступні методи) на об'єкти цього класу повинна вміти поміщати об'єкт в недійсний стан, спостерігати за тим, щоб об'єкт знаходився в недійсному стані або порушував будь-які інваріанти, умови або пост-умови класу. " - Ben Flynn
Ось приклад, подібний до @StevenKramer: у мене є @property NSArray* astronomicalEvents; в якому перераховані дані, які я хочу показати в інтерфейсі користувача. Коли програма запускає покажчик, вказує на порожній масив, то програма витягує дані з Інтернету. Коли веб-запит буде завершено (в іншому потоці) додаток будує новий масив, то атомно встановлює властивість новому значенню покажчика. Це безпечно, і мені не потрібно було писати який-небудь код блокування, якщо мені щось не вистачає. Дуже корисно для мене. - bugloaf
@HotLicks Ще один цікавий один; на певних архітектурах (не пам'ятаю, який з них), 64-бітові значення, передані як аргумент, можуть бути передані половиною в реєстрі та наполовину в стеку. atomic перешкоджає читанню напіввартості поперечної нитки. (Це була весела помилка, щоб відстежити.) - bbum
@congliu Thread А повертає об'єкт без retain/autorelease танцювати Тема B випускає об'єкт. Нитка А йде бум. atomic гарантує, що потік А має сильну довідку (+1 зберегти рахунок) для поверненого значення. - bbum


Це пояснюється в Apple документація, але нижче наведено приклади того, що насправді відбувається. Зауважте, що немає "атомного" ключового слова, якщо ви не вкажете "неатомний", то властивість атома, але явно вказати "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.

Насправді існує велика кількість різних варіантів, як ці речі працюють залежно від того, чи є властивостями скалярні значення або об'єкти, і як взаємодіяти зберігати, копіювати, читати лише, нетомічні тощо. Загалом синтезатори властивостей просто знають, як зробити "правильну річ" для всіх комбінацій.


342
2018-02-26 06:24



Не те, що замок не "гарантує безпеки нитки". - Jonathan Sterling
@ Луїс Гербарг: Я вважаю, що ваша версія (неатомний, збережений) сеттер не буде працювати належним чином, якщо ви спробуєте призначити той самий об'єкт (тобто: userName == userName_) - Florin
Ваш код трохи оманливий; існує немає гарантія того, що атомні геттери / сетери синхронізуються. Критично@property (assign) id delegate; нічого не синхронізовано (iOS SDK GCC 4.2 ARM -Os), що означає, що між ними проходить гонка [self.delegate delegateMethod:self]; і foo.delegate = nil; self.foo = nil; [super dealloc];. Побачити stackoverflow.com/questions/917884/... - tc.
@fyolnish Я не впевнений, що _val/val є, але ні, не дуже. Геттер для атома copy/retain властивість повинна гарантувати, що він не повертає об'єкт, чий рекорд становить нуль через те, що сеттер називається в іншому потоці, що, по суті, означає, що він повинен прочитати ivar, зберігати його, одночасно гарантуючи, що сеттер не переписав та не випустив його , а потім автоматично відпустіть його, щоб збалансувати збереження. Це по суті означає обидва геттер і сеттер повинні використовувати замок (якщо макет пам'яті було зафіксовано, це повинно бути здійснено з інструкціями CAS2, на жаль -retain це виклик методу). - tc.
@ tc Це було досить довго, але те, що я мав намір написати, мабуть, це: gist.github.com/fjolnir/5d96b3272c6255f6baae Але так, можливо, попереднє значення читає читач перед setFoo: повертається і випускається, перш ніж читач повертає його. Але, можливо, якщо встановлювач використовує -autorelease, замість -release, це б виправити це. - Fjölnir


Атомна

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

Неатомна

  • НЕ поведінка за замовчуванням
  • швидше (для синтезованого коду, тобто для змінних, створених за допомогою @ properties and @synthesize)
  • не різьбовий
  • може призвести до несподіваної поведінки, коли два різні процеси одночасно отримують доступ до однієї і тієї ж змінної

148
2018-05-25 10:56





Найкращим способом зрозуміти різницю є використання наступного прикладу.

Припустимо, що існує властивість атомарного рядка, що називається "name", і якщо ви телефонуєте [self setName:@"A"] від нитки А, дзвоніть [self setName:@"B"] з потоку B, і дзвоніть [self name] з потоку C, то всі операції з різними потоками будуть виконуватися послідовно, що означає, що якщо один потік виконує встановлювач або геттер, то інші потоки будуть чекати.

Це робить властивість "ім'я" читати / писати в безпеці, але якщо інший потік, D, викликає [name release] одночасно ця операція може спричинити аварійне завершення роботи, оскільки в цьому випадку відсутній виклик setter / getter. Це означає, що об'єкт є безпечним для читання / запису (ATOMIC), але не безпечним для потоку, оскільки інші потоки можуть одночасно надсилати будь-який тип повідомлень об'єкту. Розробник повинен забезпечити безпеку потоку для таких об'єктів.

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


125
2018-01-31 18:36





Синтаксис і семантика вже добре визначені іншими відмінними відповідями на це питання. Оскільки виконання і продуктивність не докладно, я додам свою відповідь.

Яка функціональна різниця між цими 3?

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

Виконання

Добре. Перше, що я хотів би з'ясувати, полягає в тому, що блокування реалізації визначається і абстраговано. Луї використовує @synchronized(self) у його прикладі - я бачив це як загальне джерело плутанини. Реалізації немає насправді використовувати @synchronized(self); він використовує рівень об'єкта спинні замки. Ілюстрація Луїсу є корисною для ілюстрації високого рівня за допомогою конструкцій, про які ми всі знайомі, але важливо знати, що він не використовується @synchronized(self).

Інша відмінність полягає в тому, що атомні властивості зберігатимуть / випускають цикл ваших об'єктів у межах геттера.

Продуктивність

Ось цікава частина: продуктивність, що використовує доступ до атомних властивостей в безперечний (наприклад, однопоточні) випадки можуть бути дуже швидкими в деяких випадках. У менш ніж ідеальних випадках використання атомних звернень може коштувати більше, ніж у 20 разів більше накладних витрат nonatomic. Поки що Оспорюваний корпус з використанням 7 потоків був у 44 разу повільний для трьохбайтової структури (2,2 ГГц Core i7 Quad Core, x86_64). Трибайтовий структур є прикладом дуже повільного властивості.

Цікава сторона примітка: визначені користувачем права доступу до трьохбайтових структур були в 52 рази швидшими, ніж синтезовані атомні додатки; або 84% - швидкість синтезованих неатомних аксесуарів.

Об'єкти, що оскаржуються, також можуть перевищити 50 разів.

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

Отже, давайте відступити ні зосереджуючись на здійсненні доступу до ресурсів, ми будемо включати звичайних підозрюваних, як objc_msgSend, а також вивчити деякі реальні результати високого рівня для багатьох дзвінків на a NSString геттер в безперечний випадки (значення в секундах):

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

Як ви, напевно, здогадалися, активність / велосипедний підрахунок підрахунків є значним спонсором з атомів і під АРК. Ви також побачите більші відмінності в оскаржених справах.

Хоча я приділяю пильну увагу продуктивності, я все ще говорю Семантика спочатку!. Тим часом, виконання багатьох проектів є низьким пріоритетом. Проте, знаючи деталі виконання та витрати на технології, які ви використовуєте, звичайно, не зашкодить. Ви повинні використовувати правильні технології для ваших потреб, цілей і здібностей. Сподіваємося, це допоможе вам заощадити кілька годин порівняння та допоможе вам приймати більш обґрунтовані рішення при розробці ваших програм.


108
2017-08-18 09:47



MRC | атомний | синтезований геттер: 47 АРК | атомний | синтезований геттер: 47 що робить їх однаковими? Чи не має АРК більше накладних витрат? - SDEZero
Отже, якщо атомні властивості погані, вони є за замовчуванням. Щоб збільшити код кошика? - Kunal Balani
@ LearnCocos2D, я пройшов тестування на 10.8.5 на тій же машині, орієнтуючись на 10.8, для односторонньої безперечної випадку з NSString яка не безсмертна: -ARC atomic (BASELINE): 100% -ARC nonatomic, synthesised: 94% -ARC nonatomic, user defined: 86% -MRC nonatomic, user defined: 5% -MRC nonatomic, synthesised: 19% -MRC atomic: 102% - результати сьогодні трохи відрізняються. Я нічого не робив @synchronized порівняння @synchronized семантично відрізняється, і я не вважаю це хорошим інструментом, якщо у вас є нетривіальні паралельні програми. якщо вам потрібна швидкість, уникайте @synchronized. - justin
чи є у вас цей тест в Інтернеті десь? Я продовжую додавати мою тут: github.com/LearnCocos2D/LearnCocos2D/tree/master/... - LearnCocos2D
@ LearnCocos2D я їх не підготував до споживання людям, вибачте. - justin


Атомна= безпека нитки

Неатомний = Ніякої безпеки потоку

Захист різьблення:

Змінні екземпляра є безпечними для потоку, якщо вони поводяться правильно, коли вони доступні з декількох потоків, незалежно від планування або перемішування виконання цих потоків середовищем виконання, і без додаткової синхронізації або іншої координації з боку викличного коду.

У нашому контексті:

Якщо потік змінює значення екземпляра, зміна значення доступна для всіх потоків, і тільки один потік може змінювати значення за один раз.

Де використовувати atomic:

якщо до змінної екземпляра буде доступ до багатопотокового середовища.

Наслідки atomic:

Не так швидко, як nonatomic оскільки nonatomic не вимагає ніяких сторожових роботів над цим з runtime.

Де використовувати nonatomic:

Якщо змінна екземпляра не буде змінена декількома потоками, ви можете використовувати його. Це покращує продуктивність.


89
2017-07-10 13:07



Все, що ви говорите тут, є правильним, але остання фраза, по суті, "неправильна", Dura, для сьогоднішнього програмування. Це дійсно незбагненно, що ви намагаєтеся "покращити продуктивність" таким чином. (Я маю на увазі, перш ніж ви отримали протягом світлих років, ви будете "не використовувати ARC", "не використовувати NSString, тому що це повільно!" І так далі.) Щоб зробити крайній приклад, було б як "команда, не залишайте коментарів у коді, оскільки це заважає нам ". Не існує реалістичного конвеєра розвитку, де ви хотіли б (неіснуючого) теоретичного зростання продуктивності на користь ненадійності. - Fattie
@JoeBlow його факт ви можете перевірити тут developer.apple.com/library/mac/documentation/Cocoa/Conceptual/... - Durai Amuthan.H
Красиво пояснив (y) - Sunil Targe


Я знайшов досить добре покладене пояснення атомних та неатомних властивостей тут. Ось декілька відповідних текстів:

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

Тому я б угадав, що атомний в даному випадку означає, що методи читача атрибутів не можуть бути перервані - фактично це означає, що змінні (ів), які читаються методом, не можуть змінити їх значення на півдорозі через те, що отримує якась інша thread / call / функція поміщений на центральний процесор.

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


67
2018-02-24 05:17