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


1851

Що означають atomicі nonatomicозначають декларації про власність?

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

У чому полягає різниця між цими трьома?


Відповіді:


1761

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

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

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

У цьому випадку, потік А може бути перейменований на об'єкт, зателефонувавши, setFirstName:а потім викликавши setLastName:. Тим часом, потік B може зателефонувати fullNameміж двома дзвінками потоку A і отримає нове ім'я в поєднанні зі старим прізвищем.

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


21
З огляду на те, що будь-який захищений від потоку код буде робити своє власне блокування і т. Д., Коли ви хочете використовувати атомні властивості властивості? У мене виникають труднощі придумати хороший приклад.
Даніель Дікісон

8
@bbum Має сенс. Мені подобається ваш коментар до ще однієї відповіді про те, що безпека ниток - це більше заклопотаність на рівні моделі. З визначення безпеки потоку IBM: ibm.co/yTEbjY "Якщо клас правильно реалізований, що є іншим способом сказати, що він відповідає його специфікації, немає послідовності операцій (читання або запис публічних полів та виклики публічних методів) на об'єктах цього класу має бути можливість перевести об'єкт у недійсний стан, спостерігати за тим, щоб об'єкт знаходився в недійсному стані, або порушував будь-яку з інваріантів, передумов або пост-умов класу ".
Бен Флінн

6
Ось приклад, схожий на @StevenKramer 's: У мене є @property NSArray* astronomicalEvents;список, який містить дані, які я хочу відображати в інтерфейсі користувача. Коли програма запускає покажчик вказує на порожній масив, програма додає дані з Інтернету. Коли веб-запит завершується (в іншому потоці), додаток створює новий масив, після чого атомно встановлює властивість на нове значення вказівника. Це безпечно для потоків, і мені не довелося писати код блокування, якщо я щось не пропускаю. Мені це здається досить корисним.
bugloaf

10
@HotLicks Ще один цікавий; у певних архітектурах (не пам'ятаю, яка з них) 64-бітові значення, передані як аргумент, можуть передаватися наполовину в регістр і половину в стеку. atomicзапобігає зчитуванням половинного значення перехресних потоків. (Це було веселою помилкою відстежити.)
bbum

8
@congliu Thread A повертає об’єкт без retain/autoreleaseтанцю. Нитка B випускає об’єкт. Нитка A іде бум . atomicгарантує, що потік A має чітке посилання (значення утримування +1) для повернутого значення.
bbum

360

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

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

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

//@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.

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


8
@Louis Gerbarg: Я вважаю, що ваша версія (неатомного, збереженого) сеттера не працюватиме належним чином, якщо ви спробуєте призначити один і той же об’єкт (тобто: userName == userName_)
Флорін

5
Ваш код трохи вводить в оману; немає немає гарантії на те , що атомні добувачі / сетера синхронізовані. Критично, @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/…
тс.

Чи не @fyolnish Я не впевнений , що _val/ valє, але ні, не зовсім. Геттер для атомної copy/ retainвластивості повинен переконатися, що він не повертає об'єкт, чий відрахування стає нульовим через виклик сеттера в інший потік, що по суті означає, що йому потрібно прочитати ivar, зберегти його, переконавшись, що сетер не має перезаписати та випустити його, а потім автоматично випустити, щоб збалансувати збереження. Це по суті означає, що і геттер, і сеттер повинні використовувати блокування (якщо компонування пам’яті було виправлено, це повинно виконуватись інструкціями CAS2; на жаль -retain, це виклик методу).
тс.

@tc Минуло досить довго, але те, що я мав на увазі написати, було це: gist.github.com/fjolnir/5d96b3272c6255f6baae Але так, старе значення може читати читач перед setFoo: повертається і випускається раніше читач повертає його. Але, можливо, якщо сетер використовував -autorelease замість -release, це виправить це.
Fjölnir

@fyolnish На жаль, ні: це автоматично випускається в потоці сеттера, тоді як його потрібно автоматично випустити на нитку геттера. Також схоже на те, що є (тонка) ймовірність закінчення стека, оскільки ви використовуєте рекурсію.
тс.

170

Атомний

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

Неатомні

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

137

Найкращий спосіб зрозуміти різницю - це наступний приклад.

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

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

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


116

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

Яка функціональна різниця між цими 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, і вивчимо деякі реальні результати високого рівня для багатьох дзвінків до NSStringгеттера у беззаперечних випадках (значення в секундах):

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

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

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


MRC | атомний | синтезований геттер: 47 ARC | атомний | синтезований геттер: 47 Що робить їх однаковими? Не повинен ARC мати більше накладних витрат?
SDEZero

2
Тож якщо атомні властивості погані, то вони є типовими. Щоб збільшити код котла?
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.
Джастін

у вас є тест десь в Інтернеті? Я продовжую додавати тут своє: github.com/LearnCocos2D/LearnCocos2D/tree/master/…
LearnCocos2D

@ LearnCocos2D я не готував їх до споживання людиною, вибачте.
Джастін

95

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

Неатомний = Відсутність безпеки потоку

Безпека нитки:

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

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

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

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

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

Наслідки atomic:

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

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

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


3
Все, що ви тут говорите, є правильним, але останнє речення, по суті, "неправильне", Дура, для сьогоднішнього програмування. Це насправді немислимо, ви б потурбувались спробувати "покращити продуктивність" таким чином. (Я маю на увазі, перш ніж потрапити в світлі роки, ви б "не використовували ARC", "не використовували NSString, тому що це повільно!" І т. Д.) Щоб зробити крайній приклад, було б як сказати "команда, не вкладайте жодних коментарів у код, оскільки це сповільнює нас ". Немає реалістичного конвеєру розвитку, де ви хотіли б (неіснуючих) теоретичних результатів заради недостовірності.
Fattie

3
@JoeBlow це факт, ви можете перевірити це тут developer.apple.com/library/mac/documentation/Cocoa/Conceptual/…
Durai Amuthan.H

1
Durai, FWIW, це посилання прямо суперечить вашій тезі "Атомна = безпека нитки". У документі Apple чітко зазначається: "Атомність властивості не є синонімом безпеки потоку об'єкта". На практиці атомних рідко достатньо для досягнення безпеки ниток.
Роб

69

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

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

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

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


1
Посилання розірвано. ; (
Роб

Ось проблема в посиланнях: (на щастя, я цитував відповідний текст у своїй відповіді
tipycalFlow

67

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

  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 - це поведінка за замовчуванням
    • Атомні аксесуари в середовищі, що не збирається сміттям (тобто при використанні утримувати / випускати / автовипускати) використовуватимуть замок, щоб переконатися, що інша нитка не заважає правильному встановленню / отриманню значення.
    • Це насправді не ключове слово.

    Приклад:

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

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

    Приклад:

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

Як призначити і сильний / зберегти обидва за замовчуванням?
BangOperator

сильний поставляється з ARC, утримувати було за замовчуванням перед ARC
abdullahselek

56

Атомний:

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

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

-(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, то атомне ключове слово синхронізується на об’єкті, оновлюючи його властивості.
Ендрю Грант

52

Найпростіша відповідь спочатку: між вашими другими двома прикладами немає різниці. За замовчуванням майнові аксесуари є атомними.

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

Для отримання додаткової інформації та інших міркувань під час створення багатопотокових програм див. Розділ « Продуктивність та нитка » документації Apple Objective-C 2.0.


8
Дві причини. По-перше, для синтезованого коду він генерується швидше (але не безпечний код). По-друге, якщо ви пишете клієнтські аксесуари, які не є атомними, це дозволяє коментувати будь-якому майбутньому користувачеві, що код не є атомним, коли він читає його інтерфейс, не змушуючи їх реалізовувати.
Луї Гербарг


31

Атомний означає, що лише одна нитка отримує доступ до змінної (статичний тип). Атомний є безпечним для ниток, але він повільний.

Неатомні засоби означають, що декілька потоків отримують доступ до змінної (динамічний тип). Неатомне є небезпечним для ниток, але воно швидко.


14

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

Це лише забезпечує безпеку нитки; це не гарантує цього. Що я маю на увазі, що ви наймаєте досвідченого водія для свого автомобіля, все ж це не гарантує, що автомобіль не зустріне ДТП. Однак ймовірність залишається найменшою.

Атомний - його неможливо розбити, тому результат очікується. При неатомному - коли інший потік отримує доступ до зони пам'яті, він може змінити його, тому результат несподіваний.

Код розмови:

Атомні роблять геттер і сетер властивості потоку безпечними. наприклад, якщо ти написав:

self.myProperty = value;

є безпечним для ниток.

[myArray addObject:@"Abc"] 

НЕ безпечно для потоків.


Я не знаю, як виходить останній абзац, але це просто неправильно, немає такого поняття, як "приватна копія".
пік

13

Не існує такого ключового слова "атомний"

@property(atomic, retain) UITextField *userName;

Ми можемо використовувати вищезгадане подібне

@property(retain) UITextField *userName;

Див. Запитання про переповнення стека. У мене виникають проблеми, якщо я використовую @property (atomic, retain) NSString * myString .


10
"Є таке ключове слово", що ключове слово за замовчуванням не потрібно і навіть це значення за замовчуванням не означає, що ключове слово не існує.
Маттін

4
Це неправильно. Ключове слово існує. Ця відповідь вводить в оману, і я б закликав її зняти.
sethfri

12

атомний (за замовчуванням)

За замовчуванням Atomic - якщо ви нічого не вводите, ваше майно є атомним. Атомна властивість гарантується, що якщо ви спробуєте прочитати з нього, ви отримаєте назад дійсне значення. Це не дає жодних гарантій щодо того, якою може бути ця цінність, але ви отримаєте хороші дані, а не лише непотрібну пам’ять. Це дозволяє вам зробити, якщо у вас є кілька потоків або кілька процесів, що вказують на одну змінну, один потік може читати, а інший - писати. Якщо вони потрапляють одночасно, потік читача гарантовано отримає одне з двох значень: або перед зміною, або після зміни. Те, що атом не дає, - це якась гарантія того, яке з цих значень ви можете отримати. Атомний насправді часто плутають із захистом від потоку, і це не правильно. Вам потрібно гарантувати безпеку своєї нитки іншими способами.

неатомічний

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

Детальніше дивіться тут: https://realm.io/news/tmi-objective-c-property-attributes/


11

За замовчуванням - 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;

Ключові слова взагалі не повинні записуватися як перший атрибут властивості.

Не забувайте, це не означає, що майно в цілому є безпечним для потоків. Лише виклик методу сеттера / геттера. Але якщо ви використовуєте сеттер і після цього геттер одночасно з двома різними нитками, його також можна зламати!


10

Перш ніж почати: Ви повинні знати, що кожен об'єкт пам'яті повинен бути розміщений з пам'яті, щоб відбувся новий письменник. Ви не можете просто писати поверх чогось, як це робите на папері. Ви повинні першим видалити (dealloc), а потім ви можете написати на нього. Якщо в даний момент стирання зроблено (або наполовину виконано) і нічого ще не було написано (або наполовину написано), і ви намагаєтесь прочитати це може бути дуже проблематичним! Атомні та неатомічні допомагають розглянути цю проблему різними способами.

Спочатку прочитайте це питання, а потім прочитайте відповідь Ббума . Крім того, тоді прочитайте моє резюме.


atomic ЗАВЖДИ буде гарантія

  • Якщо двоє різних людей хочуть читати і писати одночасно, ваш папір не просто згорить! -> Ваша заявка ніколи не вийде з ладу навіть у гоночному стані.
  • Якщо одна людина намагається писати і написала лише 4 з 8 літер для написання, то в середині не можна прочитати жодне, читання можна зробити лише тоді, коли всі 8 літер написано -> Не прочитане (дістане) станеться на "нитка, яка все ще пише", тобто якщо є 8 байт, щоб записати, і записано лише 4 байти —— до цього моменту вам заборонено читати з неї. Але так як я сказав , що це не катастрофа , то вона буде читати з значення в autoreleased об'єкта.
  • Якщо перед тим писати ви вже стерта , що раніше було написано на папері , а потім хто - то хоче читати ви можете ще прочитати. Як? Ви будете читати з чогось подібного до кошика для сміття Mac OS (оскільки кошик для сміття ще не на 100% стертий ... він знаходиться в кінцівці) ---> Якщо ThreadA буде читати, поки ThreadB вже розмовляє писати, ви отримаєте значення або від остаточного повністю записаного значення ThreadB, або отримати щось із пулу автоматичних випусків.

Зберігати підрахунки - це спосіб управління пам'яттю в Objective-C. Коли ви створюєте об'єкт, він має кількість затримок 1. Коли ви надсилаєте об'єкт збережене повідомлення, його кількість збереження збільшується на 1. Коли ви відправляєте об’єкт повідомлення про випуск, його кількість збереження зменшується на 1. Коли ви Надішліть об'єкту повідомлення про автоматичне звільнення , кількість його збереження зменшується на 1 на деякому етапі в майбутньому. Якщо кількість збережених об'єктів зменшується до 0, вона розміщується.

  • Atomic не гарантує безпеку ниток, хоча це корисно для досягнення безпеки ниток. Безпека нитки стосується того, як ви пишете свій код / ​​з якої черги потоку ви читаєте / пишете. Це гарантує лише беззбійну багатопоточність.

Що?! Чи відрізняються багатопотоковість і безпека ниток ?

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


nonatomic

  • Оскільки немає такого поняття, як Mac OS Trash Bin, то нікого не цікавить, чи завжди ви отримуєте значення (<- Це потенційно може призвести до збоїв), а також когось не хвилює, чи хтось намагається прочитати на півдорозі ваші записи (хоча На півдорозі запис у пам'яті сильно відрізняється від написання на півдорозі на папері, на пам’яті це може дати вам шалене дурне значення раніше, тоді як на папері ви бачите лише половину того, що було написано) -> Не гарантує, що не вийде з ладу, тому що він не використовує механізм автоматичного випуску.
  • Не гарантує прочитання повних письмових значень!
  • Швидше атомного

В цілому вони різні в двох аспектах:

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

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


9

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

Vijayendra Tripathi вже наводив приклад для багатопотокового середовища.


9
  • -Атомічні засоби, що лише один потік отримує доступ до змінної (статичний тип).
  • -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 ,

Тепер якщо * ім'я властивість неатоміческое потім

  • Він поверне значення "Datta" для A
  • Він поверне значення "Datta" для B

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

Тепер якщо властивість * name є атомною

  • Це забезпечить значення "Sourov" для A
  • Тоді воно поверне значення "Datta" для B

Ось чому атомний називається безпечним потоком і тому його називають безпечним для читання і запису

Така ситуаційна операція буде виконуватися серійно. І повільність у виконанні

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

- Неатомічна нитка небезпечна.

- але він швидкий у виконанні

-Nonatomic НЕ є типовою поведінкою, нам потрібно додати неатомічне ключове слово в атрибут властивості.

Для In Swift Підтвердження того, що властивості Swift неономічні в сенсі ObjC. Однією з причин є те, що ви думаєте, чи достатня атомність для власності для ваших потреб.

Довідка: https://forums.developer.apple.com/thread/25642

Для отримання додаткової інформації відвідайте веб-сайт http://rdcworld-iphone.blogspot.in/2012/12/variable-property-attributes-or.html


4
Як багато багато багато maaaaany інших сказали, atomicце НЕ поточно-! Він більш стійкий до проблем з нитками, але не є безпечним для ниток. Це просто гарантує, що ви отримаєте ціле значення, відоме також як "правильне" значення (двійковий рівень), але жодним чином не забезпечить його поточне і "правильне" значення для вашої бізнес-логіки (це може бути минулим значенням і недійсний за вашою логікою).
Алехандро Іван

6

Атомність атомна (за замовчуванням)

За замовчуванням Atomic - якщо ви нічого не вводите, ваше майно є атомним. Атомна властивість гарантується, що якщо ви спробуєте прочитати з нього, ви отримаєте назад дійсне значення. Це не дає жодних гарантій щодо того, якою може бути ця цінність, але ви отримаєте хороші дані, а не лише непотрібну пам’ять. Це дозволяє вам зробити, якщо у вас є кілька потоків або кілька процесів, що вказують на одну змінну, один потік може читати, а інший - писати. Якщо вони потрапляють одночасно, потік читача гарантовано отримає одне з двох значень: або перед зміною, або після зміни. Те, що атом не дає, - це якась гарантія того, яке з цих значень ви можете отримати. Атомний насправді часто плутають із захистом від потоку, і це не правильно. Вам потрібно гарантувати безпеку своєї нитки іншими способами.

неатомічний

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

чемність https://academy.realm.io/posts/tmi-objective-c-property-attributes/

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

Отже - якщо ви визначаєте атомну властивість у Objective-C, вона залишатиметься атомною при використанні Swift.

чемність https://medium.com/@YogevSitton/atomic-vs-non-atomic-properties-crash-course-d11c23f4366c


5

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

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


3

Атомний засіб лише один потік може одночасно отримати доступ до змінної (статичний тип). Атомний є безпечним для ниток, але він повільний.

Неатомні засоби означають, що кілька потоків можуть отримати доступ до змінної одночасно (динамічний тип). Неатомне є небезпечним для ниток, але воно швидко.


1

Якщо ви використовуєте атомну, це означає, що нитка буде безпечною і доступною лише для читання. Якщо ви використовуєте неатомічний, це означає, що кілька потоків отримують доступ до змінної і є потоком небезпечним, але він виконується швидко, виконуються операції читання і запису; це динамічний тип.


1

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

 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

Щоб спростити всю плутанину, давайте розберемося з блокуванням mtex.

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

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


-1

Атомний: Забезпечте безпеку ниток, зафіксувавши різьбу за допомогою NSLOCK.

Неатомний: не забезпечує безпеку ниток, оскільки немає механізму фіксації різьби.


-1

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

Неатомні властивості : - Коли змінна, призначена атомною властивістю, означає, що вона має багатопотоковий доступ, і вона не буде безпечною для потоків і буде повільною в перспективі продуктивності, матиме поведінку за замовчуванням і коли два різні потоки хочуть отримати доступ до змінної одночасно це дасть несподівані результати.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.