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

<p>что <code>atomic</code> и <code>nonatomic</code> означают в объявлениях свойств?</p><pre><code>@property(nonatomic, retain) uitextfield *username; @property(atomic, retain) uitextfield *username; @property(retain) uitextfield *username; </code></pre><p>в чем заключается оперативная разница между этими тремя?</p>

<p>последние два идентичны; "атомное" - это поведение по умолчанию (<strike>обратите внимание, что на самом деле это не ключевое слово; это определяется только отсутствием <code>nonatomic</code></strike> - <code>atomic</code> был добавлен в качестве ключевого слова в последних версиях llvm/clang).</p><p>предполагая, что вы @synthesizing реализации метода, атомарный против неатомарного изменения сгенерированного кода. если вы пишете свой собственный установщик/получатель, атомарный/неатомный/сохранить/назначить/копировать просто рекомендации. (примечание: @synthesize теперь является поведением по умолчанию в последних версиях llvm. также нет необходимости объявлять переменные экземпляра; они также будут автоматически синтезироваться, и к их имени будет добавлен <code>\_</code> для предотвращения случайного прямого доступа).</p><p>с "атомарным" синтезированный установщик/получатель гарантирует, что <em> целое </em> значение всегда возвращается из получателя или устанавливается установщиком, независимо от действия установщика в любой другой теме. то есть, если поток a находится в середине метода получения, а поток b вызывает метод установки, фактическое жизнеспособное значение - объект с автоматически выпускаемым кодом, скорее всего, - будет возвращено вызывающей стороне в a.</p><p>в <code>nonatomic</code> такие гарантии не предоставляются. таким образом, <code>nonatomic</code> значительно быстрее, чем "атомарный".</p><p>то, что делает "атомарный" <strong>не</strong> делает, это делает любые гарантии безопасности потока. если поток a вызывает метод получения одновременно, а поток b и c вызывают метод установки с различными значениями, поток a может получить любое одно из трех возвращенных значений - одно до вызова любого метода установки или любое из значений, переданных в методы установки в b и c. аналогичным образом, объект может в конечном итоге получить значение из b или c, никак не сказать.</p><p>обеспечение целостности данных - одна из основных задач многопоточного программирования - достигается другими средствами.</p><p>добавление к этому:</p><p><code>atomicity</code> отдельного свойства также не может гарантировать безопасность потока, когда в игре находятся несколько зависимых свойств.</p><p>рассматривать:</p><pre><code> @property(atomic, copy) nsstring *firstname; @property(atomic, copy) nsstring *lastname; @property(readonly, atomic, copy) nsstring *fullname; </code></pre><p>в этом случае поток a может переименовывать объект, вызывая <code>setfirstname:</code>, а затем вызывая <code>setlastname:</code>. между тем, поток b может вызвать <code>fullname</code> между двумя вызовами потока a и получит новое имя в сочетании со старой фамилией.</p><p>чтобы решить эту проблему, вам нужна <em> транзакционная модель </em>. то есть какой-то другой вид синхронизации и/или исключения, позволяющий исключить доступ к <code>fullname</code> во время обновления зависимых свойств.</p>

<p>это объясняется в apple <a href="http://developer.apple.com/library/mac/#documentation/cocoa/conceptual/objectivec/chapters/ocproperties.html">документация</a> , но ниже приведены некоторые примеры того, что на самом деле происходит. обратите внимание, что ключевое слово "atomic" отсутствует, если вы не укажете "nonatomic", тогда свойство является атомарным, но явное указание "atomic" приведет к ошибке.</p><pre><code>//@property(nonatomic, retain) uitextfield *username; //generates roughly - (uitextfield *) username { return username; } - (void) setusername:(uitextfield *)username\_ { [username\_ retain]; [username release]; username = username\_; } </code></pre><p>теперь атомный вариант немного сложнее:</p><pre><code>//@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\_; } } </code></pre><p>по сути, атомарная версия должна блокироваться, чтобы гарантировать безопасность потока, а также увеличивает счетчик ссылок на объект (и счет автоматического выпуска, чтобы сбалансировать его), так что объект гарантированно существует для вызывающей стороны, в противном случае является потенциальным условием гонки, если другой поток устанавливает значение, в результате чего счетчик ссылок падает до 0.</p><p>на самом деле существует большое количество различных вариантов того, как эти вещи работают, в зависимости от того, являются ли свойства скалярными значениями или объектами, и как взаимодействуют операции сохранения, копирования, чтения, неатома и т.д. в общем, синтезаторы свойств просто знают, как сделать "правильную вещь" для всех комбинаций.</p>

<h3>атомное</h3><ul> <li>поведение по умолчанию</li> <li>обеспечит завершение текущего процесса цп, прежде чем другой процесс получит доступ к переменной</li> <li>не быстрый, так как он гарантирует, что процесс завершен</li> </ul><h3>неатомарный</h3><ul> <li>не является поведением по умолчанию</li> <li>быстрее (для синтезированного кода, то есть для переменных, созданных с использованием @property и @synthesize)</li> <li>не потокобезопасный</li> <li>может привести к непредвиденному поведению, когда два разных процесса одновременно обращаются к одной и той же переменной</li> </ul>

<p>лучший способ понять разницу - использовать следующий пример.</p><p>предположим, что есть атомарное строковое свойство с именем "name", и если вы вызываете <code>[self setname:@"a"]</code> из потока a, вызываете <code>[self setname:@"b"]</code> из потока b и вызываете <code>[self name]</code> из потока c, то все операции в разных потоках будут выполняться последовательно, что означает, что один поток выполнение установщика или получателя, тогда другие потоки будут ждать.</p><p>это делает свойство "name" доступным для чтения/записи, но если другой поток, d, вызывает <code>[name release]</code> одновременно, то эта операция может привести к сбою, потому что здесь нет вызова setter/getter. это означает, что объект является безопасным для чтения/записи (atomic), но не потокобезопасным, поскольку другие потоки могут одновременно отправлять объекту сообщения любого типа. разработчик должен обеспечить безопасность потоков для таких объектов.</p><p>если свойство "name" было неатомичным, то все потоки в приведенном выше примере - a, b, c и d будут выполняться одновременно, что приведет к непредсказуемому результату. в случае атомарного, один из a, b или c будет выполняться первым, но d все еще может выполняться параллельно.</p>

<p>синтаксис и семантика уже хорошо определены другими превосходными ответами на этот вопрос. поскольку <em> выполнение </em> и <em> производительность </em> не детализированы, я добавлю свой ответ.</p><blockquote> <p>в чем функциональная разница между этими 3?</p> </blockquote><p>я всегда считал атомную по умолчанию довольно любопытной. на уровне абстракции мы работаем над использованием атомарных свойств для класса в качестве транспортного средства для достижения 100% -ной безопасности потока - это угловой случай. для действительно правильных многопоточных программ вмешательство программиста почти наверняка является требованием. между тем, характеристики производительности и исполнения еще не были подробно описаны. написав несколько многопоточных программ за эти годы, я все время объявлял свои свойства как <code>nonatomic</code>, потому что atomic не был пригоден для каких-либо целей. во время обсуждения деталей атомных и неатомных свойств <a href="https://stackoverflow.com/questions/12010211/use-of-atomic-properties-in-objective-c-any-side-effects">этот вопрос</a> , я сделал некоторые профилирования столкнулся с некоторыми любопытными результатами.</p><p><strong> исполнение </strong></p><p>хорошо. первое, что я хотел бы прояснить, это то, что реализация блокировки определяется реализацией и абстрагируется. луи использует <code>@synchronized(self)</code> в своем примере - я видел это как общий источник путаницы. реализация <em> на самом деле </em> не использует <code>@synchronized(self)</code>; он использует объектный уровень <em> спин блокировки </em>. иллюстрация луи хороша для иллюстрации высокого уровня, использующей конструкции, с которыми мы все знакомы, но важно знать, что она не использует <code>@synchronized(self)</code>.</p><p>другое отличие состоит в том, что атомарные свойства будут сохранять/освобождать цикл ваших объектов в геттере.</p><p><strong> производительность </strong></p><p>вот интересная часть: производительность, использующая доступ к атомарным свойствам в <strong> неоспоримых </strong> (например, однопоточных) случаях, может быть действительно очень высокой в некоторых случаях. в далеко не идеальных случаях использование атомарного доступа может стоить более чем в 20 раз дороже <code>nonatomic</code>. в то время как <strong> оспариваемый </strong> случай использования 7 потоков был в 44 раза медленнее для трехбайтовой структуры (2,2 ггц <a href="https://en.wikipedia.org/wiki/intel\_core#core\_i7">core i7</a> quad-core x86\_64). трехбайтовая структура является примером очень медленного свойства.</p><p>интересное примечание: определяемые пользователем средства доступа трехбайтовой структуры были в 52 раза быстрее, чем синтезированные атомарные средства доступа; или 84% скорости синтезированных неатомных акцессоров.</p><p>объекты в оспариваемых случаях также могут превышать 50 раз.</p><p>из-за большого количества оптимизаций и вариаций в реализации очень сложно измерить реальные воздействия в этих контекстах. вы можете часто слышать что-то вроде "доверяйте этому, если вы не профилируете и не обнаружите, что это проблема". из-за уровня абстракции на самом деле довольно сложно измерить фактическое влияние. сбор фактических затрат из профилей может занять очень много времени, а из-за абстракций довольно неточен. кроме того, arc против mrc может иметь большое значение.</p><p>итак, давайте вернемся назад (<em>, а не </em>, фокусируясь на реализации доступа к свойствам, мы включим обычных подозреваемых, таких как <code>objc\_msgsend</code>, и исследуем некоторые реальные высокоуровневые результаты для многих вызовов <code>nsstring</code> getter в <em> неоспоримых </em> случаях (значения в секундах):</p><ul> <li>mrc | неатомный | внедренные вручную геттеры: 2</li> <li>mrc | неатомный | синтезированный геттер: 7</li> <li>mrc | атомный | синтезированный геттер: 47</li> <li>arc | неатомный | синтезированный геттер: 38 (примечание: arc добавляет количество циклов отсчета здесь)</li> <li>arc | атомный | синтезированный геттер: 47</li> </ul><p>как вы, наверное, догадались, активность/циклический подсчет ссылок вносит существенный вклад в атомарность и в arc. вы также увидите большие различия в спорных случаях.</p><p>хотя я уделяю пристальное внимание производительности, я все же говорю <strong> семантика первая! </strong>. между тем, производительность является низким приоритетом для многих проектов. однако знание деталей исполнения и стоимости используемых вами технологий, безусловно, не повредит. вы должны использовать правильную технологию для ваших нужд, целей и способностей. надеюсь, это сэкономит вам несколько часов сравнений и поможет вам принять более взвешенное решение при разработке ваших программ.</p>

<p><strong>атомарный</strong> = потокобезопасность</p><p><strong>не атомарный</strong> = нет безопасности потока</p><h2>поток безопасности:</h2><p>переменные экземпляра являются поточно-ориентированными, если они ведут себя корректно при доступе из нескольких потоков, независимо от планирования или чередования выполнения этих потоков средой выполнения, и без дополнительной синхронизации или другой координации со стороны вызывающего кода.</p><h2>в нашем контексте:</h2><p>если поток изменяет значение экземпляра, измененное значение доступно всем потокам, и только один поток может изменить значение за раз.</p><h2>где использовать <code>atomic</code>:</h2><p>если переменная экземпляра будет доступна в многопоточной среде.</p><h2>значение <code>atomic</code>:</h2><p>не так быстро, как <code>nonatomic</code>, потому что <code>nonatomic</code> не требует никакой надзорной работы над этим из среды выполнения.</p><h2>где использовать <code>nonatomic</code>:</h2><p>если переменная экземпляра не будет изменена несколькими потоками, вы можете использовать ее. это улучшает производительность.</p>

<p>я нашел довольно удачное объяснение атомных и неатомных свойств <a href="http://archive.atomicmpc.com.au/forums.asp?s=2&c=10&t=4594">здесь</a> . вот некоторые соответствующие тексты из того же:</p><blockquote> <p>"атомный" означает, что его нельзя сломать. в терминах os/программирования вызов атомарной функции - это вызов, который не может быть прерван - вся функция должна быть выполнена, а не выгружена из цпу обычным переключением контекста ос до его завершения. просто на тот случай, если вы не знали: поскольку цп может делать только одну вещь за раз, ос вращает доступ к цп всем запущенным процессам за небольшие промежутки времени, чтобы создать иллюзию <em> </em> многозадачности. планировщик цп может (и делает) прерывать процесс в любой момент его выполнения - даже в середине вызова функции. таким образом, для таких действий, как обновление переменных общего счетчика, когда два процесса могут попытаться обновить переменную одновременно, они должны выполняться "атомарно", т. е. каждое действие обновления должно завершиться полностью, прежде чем любой другой процесс может быть перенесен на цпу.</p> <p>таким образом, я бы предположил, что в этом случае атомарный означает, что методы чтения атрибутов не могут быть прерваны - в действительности это означает, что переменная (и), читаемая методом, не может изменить свое значение на полпути, потому что какой-то другой поток/вызов/функция получает поменял местами процессор.</p> </blockquote><p>поскольку переменные <code>atomic</code> не могут быть прерваны, значение, содержащееся в них в любой точке, является (thread-lock) гарантированно <strong> не поврежденным </strong>, хотя, гарантируя это блокировка потоков замедляет доступ к ним. переменные <code>non-atomic</code>, с другой стороны, не дают такой гарантии, но предлагают роскошь более быстрого доступа. подводя итог, используйте <code>non-atomic</code>, когда вы знаете, что ваши переменные не будут доступны нескольким потокам одновременно, и это ускорит процесс.</p>

<p>после прочтения очень многих статей, публикаций stack overflow и создания демонстрационных приложений для проверки атрибутов переменных свойств, я решил собрать всю информацию об атрибутах:</p><ol> <li><code>atomic</code> // по умолчанию</li> <li><code>nonatomic</code></li> <li><code>strong = retain</code> // по умолчанию</li> <li><code>weak = unsafe\_unretained</code></li> <li><code>retain</code></li> <li><code>assign</code> // по умолчанию</li> <li><code>unsafe\_unretained</code></li> <li><code>copy</code></li> <li><code>readonly</code></li> <li><code>readwrite</code> // по умолчанию</li> </ol><p>в статье <em> <a href="http://rdcworld-iphone.blogspot.in/2012/12/variable-property-attributes-or.html"><strong> атрибуты или переменные свойства переменных в ios </strong></a> </em> вы можете найти все вышеперечисленные атрибуты, и это, безусловно, поможет вам.</p><ol> <li> <p><strong><code>atomic</code></strong></p> <ul> <li><code>atomic</code> означает, что только один поток имеет доступ к переменной (статический тип).</li> <li><code>atomic</code> является потокобезопасным.</li> <li>но это медленно в производительности</li> <li><code>atomic</code> - поведение по умолчанию</li> <li>атомарные методы доступа в среде без сборки мусора (т.е. при использовании retain/release/autorelease) будут использовать блокировку, чтобы гарантировать, что другой поток не будет мешать правильной установке/получению значения.</li> <li>на самом деле это не ключевое слово.<br> <br></li> </ul> <p>пример:</p> <pre><code> @property (retain) nsstring *name; @synthesize name; </code></pre></li> <li> <p><strong><code>nonatomic</code></strong></p> <ul> <li><code>nonatomic</code> означает многопоточный доступ к переменной (динамический тип).</li> <li><code>nonatomic</code> небезопасен.</li> <li>но это быстро в производительности</li> <li><code>nonatomic</code> не является поведением по умолчанию. нам нужно добавить ключевое слово <code>nonatomic</code> в атрибуте свойства.</li> <li>это может привести к неожиданному поведению, когда два разных процесса (потока) одновременно обращаются к одной и той же переменной.<br> <br></li> </ul> <p>пример:</p> <pre><code> @property (nonatomic, retain) nsstring *name; @synthesize name; </code></pre></li> </ol>

<h2><strong>атомная :</strong></h2><p>атомные гарантии, что доступ к собственности будет осуществляться атомарным способом. например. он всегда возвращает полностью инициализированные объекты, любое получение/установка свойства в одном потоке должно завершиться, прежде чем другой сможет получить к нему доступ.</p><p>если вы представите следующую функцию, выполняющуюся в двух потоках одновременно, вы поймете, почему результаты не будут хорошими.</p><pre><code>-(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; } ... } </code></pre><p><strong>плюсы:</strong> возврат полностью инициализированных объектов каждый раз делает его лучшим выбором в случае многопоточности.</p><p><strong>минусы:</strong> хит производительности, делает выполнение немного медленнее</p><h2><strong>не атомарный :</strong></h2><p>в отличие от atomic, он не гарантирует, что каждый раз полностью инициализированный объект возвращается.</p><p><strong>плюсы:</strong> чрезвычайно быстрое выполнение.</p><p><strong>минусы:</strong> возможны значения мусора в случае многопоточности.</p>

<p>самый простой ответ: нет разницы между вашими вторыми примерами. по умолчанию средства доступа к свойствам являются атомарными.</p><p>атомарные методы доступа в среде без сборки мусора (т.е. при использовании retain/release/autorelease) будут использовать блокировку, чтобы гарантировать, что другой поток не будет мешать правильной установке/получению значения.</p><p>см. раздел " <a href="http://www.scribd.com/doc/121014348/89/performance-and-threading">производительность и многопоточность</a> " документации apple objective-c 2.0 для получения дополнительной информации и других соображений при создании многопоточных приложений.</p>

<p>атомный означает, что только один поток обращается к переменной (статический тип). атомный потокобезопасный, но он медленный.</p><p>неатомарный означает, что несколько потоков обращаются к переменной (динамический тип). nonatomic небезопасен, но он быстр.</p>

<p>атомный <strong>потокобезопасный</strong>, это <strong>медленный</strong> и это <strong>хорошо (не гарантировано)</strong>, что предоставляется только заблокированное значение независимо от того, сколько потоков пытаются получить доступ через ту же зону. при использовании atomic часть кода, написанная внутри этой функции, становится частью критической секции, в которую одновременно может работать только один поток.</p><p>это только гарантирует безопасность потока; это не гарантирует этого. <strong>я имею в виду, что вы нанимаете опытного водителя для своей машины, но это не гарантирует, что автомобиль не попадет в аварию. однако вероятность остается малейшей.</strong></p><p>атомное - его нельзя сломать, поэтому результат ожидаем. с неатомарным - когда другой поток обращается к зоне памяти, он может изменить ее, поэтому результат будет неожиданным.</p><p>обсуждение кода:</p><p>атомный make getter и setter свойства thread безопасны. например, если вы написали:</p><pre><code>self.myproperty = value; </code></pre><p>поток безопасен.</p><pre><code>[myarray addobject:@"abc"] </code></pre><p>не является потокобезопасным.</p>

<p><strong> нет такого ключевого слова "атомный" </strong></p><pre><code>@property(atomic, retain) uitextfield *username; </code></pre><p>мы можем использовать выше, как</p><pre><code>@property(retain) uitextfield *username; </code></pre><p>см. вопрос переполнения стека <em> <a href="https://stackoverflow.com/questions/8036604">у меня возникают проблемы, если я использую @property (atomic, retain) nsstring * mystring</a> </em>.</p>

<p>значение по умолчанию <strong> </strong> равно <code>atomic</code>, это означает, что оно всегда снижает производительность, когда вы используете это свойство, но оно поточно-ориентировано. что делает objective-c, так это устанавливает блокировку, поэтому только фактический поток может получить доступ к переменной, пока выполняется установщик/получатель.</p><p>пример с mrc для свойства с ivar \_internal:</p><pre><code>[\_internal lock]; //lock id result = [[value retain] autorelease]; [\_internal unlock]; return result; </code></pre><p>итак, последние два одинаковы:</p><pre><code>@property(atomic, retain) uitextfield *username; @property(retain) uitextfield *username; // defaults to atomic </code></pre><p>с другой стороны, <code>nonatomic</code> ничего не добавляет к вашему коду. так что это только потокобезопасно, если вы сами создадите механизм безопасности.</p><pre><code>@property(nonatomic, retain) uitextfield *username; </code></pre><p><em> ключевые слова вообще не должны записываться как первый атрибут свойства. </em></p><p><strong> не забывайте, это не означает, что свойство в целом является потокобезопасным. только вызов метода метода установки/получения. но если вы используете установщик, а затем одновременно получатель с двумя разными потоками, он тоже может быть нарушен! </strong></p>

<blockquote> <p>атомарный (по умолчанию)</p> <p>по умолчанию используется атомарный: если вы ничего не печатаете, ваше свойство атомарное. атомарное свойство гарантировано, что если вы попытаетесь прочитать из него, вы получите верное значение. это не дает никаких гарантий относительно того, каким может быть это значение, но вы получите хорошие данные, а не только ненужную память. это позволяет вам делать, если у вас есть несколько потоков или несколько процессов, указывающих на одну переменную, один поток может читать, а другой поток может писать. если они попадают в одно и то же время, поток чтения гарантированно получит одно из двух значений: либо до изменения, либо после изменения. то, что не дает вам атомарность, это какая-то гарантия того, какие из этих ценностей вы можете получить. atomic обычно путают с поточностью потоков, и это не правильно. вы должны гарантировать безопасность вашей нити другими способами. тем не менее, atomic гарантирует, что если вы попытаетесь читать, вы получите какое-то значение.</p> <p>неатомической</p> <p>с другой стороны, неатомарное, как вы, вероятно, можете догадаться, просто означает "не делайте этого атомарного материала". то, что вы теряете, - это гарантия того, что вы всегда что-то получите. если вы попытаетесь прочитать во время записи, вы можете получить данные с мусором. но, с другой стороны, вы идете немного быстрее. поскольку атомарные свойства должны творить чудеса, чтобы гарантировать возвращение значения, они немного медленнее. если это свойство, к которому вы часто обращаетесь, вы можете перейти к неатомному, чтобы убедиться, что вы не понесете этот штраф за скорость.</p> </blockquote><p>подробнее здесь: <a href="https://realm.io/news/tmi-objective-c-property-attributes/">https://realm.io/news/tmi-objective-c-property-attributes/</a> </p>

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

<p>прежде чем начать: вы должны знать, что каждый объект в памяти должен быть освобожден из памяти, чтобы произошла новая запись. вы не можете просто написать поверх чего-либо, как на бумаге. вы <strong> должны </strong> сначала стереть (сдать) его, а затем вы можете написать на него. если в тот момент, когда стирание выполнено (или наполовину выполнено) и ничего <strong> еще не было </strong> записано (или наполовину записано), и вы пытаетесь прочитать, это может быть очень проблематичным! атомные и неатомные помогают вам по-разному относиться к этой проблеме.</p><p>сначала прочитайте <a href="https://stackoverflow.com/questions/21098494/atomic-properties-vs-thread-safe-in-objective-c">это</a> вопрос, а затем прочитайте <a href="https://stackoverflow.com/a/589392/5175709">ответ бомба</a> . кроме того, тогда прочитайте мое резюме.</p><hr><p><strong> <code>atomic</code> всегда будет гарантировать </strong></p><ul> <li>если два разных человека хотят читать и писать одновременно, ваша статья не просто сгорит! -> ваше приложение никогда не потерпит крах, даже в состоянии гонки.</li> <li>если один человек пытается написать и написал только 4 из 8 писем для записи, то не может читать в середине, чтение может быть выполнено только тогда, когда написаны все 8 букв -> не читается (получит) произойдет "поток, который все еще пишет", т. е. если в байтах записано 8 байтов, а записано только 4 байта - до этого момента вы не можете читать из него. но так как я сказал, что он не будет аварийно завершать работу, он будет считывать значение из <em> объекта autoreleased </em>.</li> <li>если <strong> перед </strong> написанием вы <strong> </strong> стерли то, что было ранее написано на бумаге, и тогда кто-то хочет прочитать вас <em> может </em> все еще читать. как? вы будете читать что-то похожее на мусорное ведро mac os (так как мусорное ведро еще не удалено на 100% ... оно находится в подвешенном состоянии) ---> если threada должен читать, а threadb уже освобожден для записи, вы получите значение из окончательного полностью записанного значения threadb или получение чего-либо из пула автоматического выпуска.</li> </ul><blockquote> <p>сохранять счетчики - это способ управления памятью в objective-c. когда вы создаете объект, он имеет счет сохранения 1. когда вы отправляете объекту сообщение сохранения, его счет хранения увеличивается на 1. когда вы отправляете объекту сообщение об освобождении, его счет хранения уменьшается на 1. когда вы отправьте объекту <strong> сообщение об автозапуске </strong>, его счетчик хранения будет уменьшен на 1 на каком-то этапе в будущем. если количество сохраняемых объектов уменьшается до 0, оно освобождается.</p> </blockquote><ul> <li>atomic <strong> не </strong> не гарантирует безопасность потока, хотя это полезно для достижения безопасности потока. потокобезопасность относится к тому, как вы пишете свой код/из какой очереди потока вы читаете/пишете. это гарантирует только неразрушаемую многопоточность.</li> </ul><hr><p><strong> что ?! многопоточность и <a href="https://stackoverflow.com/questions/261683/what-is-meant-by-thread-safe-code">потокобезопасность</a> отличаются? </strong></p><p>да. многопоточность означает: несколько потоков могут одновременно читать общий фрагмент данных, и мы не будем аварийно завершать работу, но это не гарантирует, что вы не читаете из неавторизованного значения. с безопасностью потока гарантируется, что то, что вы читаете, не высвобождается автоматически. причина, по которой мы не делаем все атомарным по умолчанию, заключается в том, что производительность снижается, и для большинства вещей действительно не требуется безопасность потоков. несколько частей нашего кода нуждаются в этом, и для этих нескольких частей нам нужно писать наш код потокобезопасным способом, используя блокировки, мьютекс или синхронизацию.</p><hr><p><strong><code>nonatomic</code></strong></p><ul> <li>поскольку не существует такой вещи, как мусорное ведро mac os, то никого не волнует, всегда ли вы получаете значение (<- это может привести к сбою), и никому нет дела, если кто-то пытается прочитать в середине вашего письма (хотя наполовину запись в памяти сильно отличается от написания наполовину на бумаге, в памяти это может дать вам сумасшедшее глупое значение, в то время как на бумаге вы видите только половину написанного) -> не гарантирует, что не произойдет сбой, потому что это не использует механизм автоматического выпуска.</li> <li>не гарантирует полного написания значений для чтения!</li> <li>быстрее атомного</li> </ul><hr><p>в целом они отличаются в 2 аспектах:</p><ul> <li> <p>сбой или нет из-за наличия или отсутствия пула авто-релиза.</p> </li> <li> <p>разрешить чтение прямо в середине "еще не законченной записи или пустого значения" или не разрешить и разрешить чтение только тогда, когда значение <em> полностью </em> записано.</p> </li> </ul>

<ul> <li><strong> - атомарный означает, что только один поток имеет доступ к переменной (статический тип). </strong></li> <li><strong> - atomic является потокобезопасным. </strong></li> <li><strong> - но производительность низкая </strong></li> </ul><p><strong> как объявить: </strong></p><p>как атомная по умолчанию,</p><pre><code>@property (retain) nsstring *name; </code></pre><p>и в файле реализации</p><pre><code>self.name = @"sourov"; </code></pre><p>предположим, что задача, связанная с тремя свойствами</p><pre><code> @property (retain) nsstring *name; @property (retain) nsstring *a; @property (retain) nsstring *b; self.name = @"sourov"; </code></pre><p>все свойства работают параллельно (как асинхронно).</p><p>если вы называете "имя" из потока <strong>a</strong>,</p><p><strong> и </strong></p><p>в то же время, если вы звоните</p><pre><code>[self setname:@"datta"] </code></pre><p>из потока <strong>b</strong>,</p><p><strong> теперь, если * свойство name неатомное </strong>, тогда</p><ul> <li>вернет значение "датта" для а</li> <li>он вернет значение "датта" для b</li> </ul><p><em> вот почему non atomic называется небезопасным потоком, но он работает быстро из-за параллельного выполнения </em></p><p><strong> теперь, если * свойство name является атомарным </strong></p><ul> <li>это обеспечит значение "sourov" для a</li> <li>тогда он вернет значение "датта" для b</li> </ul><p><strong> <em> вот почему атомарность называется потокобезопасной </em> </strong> и <strong> <em> именно поэтому он называется безопасным для чтения и записи </em> </strong></p><p>такая ситуация операция будет выполнять поочередно. <strong> и низкая производительность </strong></p><p><strong> - неатомарный означает, что многопоточный доступ к переменной (динамический тип). </strong></p><p><strong> - неатомический поток небезопасен. </strong></p><p><strong> - но это быстро по производительности </strong></p><p><strong> - nonatomic не является поведением по умолчанию, нам нужно добавить ключевое слово nonatomic в атрибуте свойства. </strong></p><p>for in swift подтверждение того, что свойства swift неатомичны в смысле objc. одна из причин заключается в том, что вы думаете о том, достаточна ли атомарность для каждого объекта для ваших нужд.</p><p>ссылка: <a href="https://forums.developer.apple.com/thread/25642">https://forums.developer.apple.com/thread/25642</a> </p><p>для получения дополнительной информации посетите веб-сайт <a href="http://rdcworld-iphone.blogspot.in/2012/12/variable-property-attributes-or.html">http://rdcworld-iphone.blogspot.in/2012/12/variable-property-attributes-or.html</a> </p>

<p>прежде чем обсуждать атрибуты @property, вы должны знать, для чего используется @property. @property предлагает способ определить информацию, которую класс должен инкапсулировать. если вы объявите объект/переменную с помощью @property, то этот объект/переменная будет доступен для других классов, импортирующих его класс. если вы объявляете объект с помощью @property в заголовочном файле, то вы должны синтезировать его с помощью @synthesize в файле реализации.</p><p>пример:</p><p>.х класс</p><pre><code>@interface exampleclass : nsobject @property (nonatomic, retain) nsstring *name; @end </code></pre><p>.m класс</p><pre><code>@implementation exampleclass @synthesize name; @end </code></pre><p>теперь компилятор будет синтезировать методы доступа для имени.</p><pre><code>exampleclass *newobject=[[exampleclass alloc]init]; nsstring *name1=[newobject name]; // get 'name' [obj setname:@“tiger”]; </code></pre><p>список атрибутов @property: atomic. неатомический. сохранить. копия. неизменяемые. читай пиши. назначить. сильный.</p><p>atomic: это поведение по умолчанию. если объект объявлен как атомарный, он становится потокобезопасным. потокобезопасный означает, что одновременно только один поток определенного экземпляра этого класса может иметь контроль над этим объектом.</p><p>пример :</p><pre><code>@property nsstring *name; //by default atomic @property (atomic)nsstring *name; // explicitly declared atomic </code></pre><p>неатомный: не является потокобезопасным. вы можете использовать атрибут неатомического свойства, чтобы указать, что синтезированные средства доступа просто устанавливают или возвращают значение напрямую, без каких-либо гарантий относительно того, что произойдет, если к одному и тому же значению обращаются одновременно из разных потоков. по этой причине доступ к неатомарному свойству быстрее, чем к атомарному. <code>@property (nonatomic)nsstring *name;</code></p><p>retain: требуется, когда атрибут является указателем на объект. метод setter увеличивает количество сохраняемых объектов, так что он будет занимать память в пуле автоматического выпуска. <code>@property (retain)nsstring *name;</code></p><p>копия: если вы используете копию, вы не можете использовать сохранить. использование экземпляра экземпляра класса будет содержать собственную копию. даже если изменяемая строка установлена и впоследствии изменена, экземпляр захватывает любое значение, которое он имеет во время его установки. методы получения и получения не будут синтезированы.</p><pre><code>@property (copy) nsstring *name; nsmutablestring *namestring = [nsmutablestring stringwithstring:@"liza"]; xyzobj.name = namestring; [namestring appendstring:@"pizza"]; </code></pre><p>только для чтения: если вы не хотите разрешать изменение свойства с помощью метода установки, вы можете объявить свойство только для чтения. <code>@property (readonly) nsstring *name;</code></p><p>readwrite: это поведение по умолчанию. вам не нужно явно указывать атрибут readwrite.</p><p><code>@property (readwrite) nsstring *name;</code></p><p>assign: создаст установщик, который присваивает значение переменной экземпляра напрямую, а не копирует или сохраняет его. это лучше всего подходит для примитивных типов, таких как nsinteger и cgfloat, или для объектов, которыми вы не владеете напрямую, таких как делегаты.</p><p><code>@property (assign) nsinteger year;</code></p><p>сильный: это замена для удержания. <code>@property (nonatomic, strong) avplayer *player;</code></p><p>unsafe\_unretained: в какао и какао touch есть несколько классов, которые еще не поддерживают слабые ссылки, что означает, что вы не можете объявить слабое свойство или слабую локальную переменную, чтобы отслеживать их. эти классы включают nstextview, nsfont и nscolorspace и т.д. если вам нужно использовать слабую ссылку на один из этих классов, вы должны использовать небезопасную ссылку. небезопасная ссылка похожа на слабую ссылку в том, что она не поддерживает связанный объект, но для него не будет установлено значение nil, если целевой объект освобожден.</p><p><code>@property (unsafe\_unretained) nsobject *unsafeproperty;</code></p>

<p>свойство atomic гарантирует сохранение полностью инициализированного значения независимо от того, сколько потоков выполняет для него getter & setter.</p><p>неатомарное свойство указывает, что синтезированные методы доступа просто устанавливают или возвращают значение напрямую, без каких-либо гарантий относительно того, что произойдет, если к одному и тому же значению обращаются одновременно из разных потоков.</p>

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

<p><strong> <em> атомарность (по умолчанию) </em> </strong></p><p>по умолчанию используется атомарный: если вы ничего не печатаете, ваше свойство атомарное. атомарное свойство гарантировано, что если вы попытаетесь прочитать из него, вы получите верное значение. это не дает никаких гарантий относительно того, каким может быть это значение, но вы получите хорошие данные, а не только ненужную память. это позволяет вам делать, если у вас есть несколько потоков или несколько процессов, указывающих на одну переменную, один поток может читать, а другой поток может писать. если они попадают в одно и то же время, поток чтения гарантированно получит одно из двух значений: либо до изменения, либо после изменения. то, что не дает вам атомарность, это какая-то гарантия того, какие из этих ценностей вы можете получить. atomic обычно путают с поточностью потоков, и это не правильно. вы должны гарантировать безопасность вашей нити другими способами. тем не менее, atomic гарантирует, что если вы попытаетесь читать, вы получите какое-то значение.</p><p><strong> <em> неатомической </em> </strong></p><p>с другой стороны, неатомарное, как вы, вероятно, можете догадаться, просто означает "не делайте этого атомарного материала". то, что вы теряете, - это гарантия того, что вы всегда что-то получите. если вы попытаетесь прочитать во время записи, вы можете получить данные с мусором. но, с другой стороны, вы идете немного быстрее. поскольку атомарные свойства должны творить чудеса, чтобы гарантировать возвращение значения, они немного медленнее. если это свойство, к которому вы часто обращаетесь, вы можете перейти к неатомному, чтобы убедиться, что вы не понесете этот штраф за скорость. доступ</p><p>вежливость <a href="https://academy.realm.io/posts/tmi-objective-c-property-attributes/">https://academy.realm.io/posts/tmi-objective-c-property-attributes/</a> </p><p><strong> атрибуты свойства атомарности (атомарные и неатомарные) не отражены в соответствующем объявлении свойства swift, но гарантии атомарности реализации objective-c все еще сохраняются, когда импортируемое свойство доступ из свифта. </strong></p><p><strong> итак, если вы определите атомарное свойство в objective-c, оно останется атомарным при использовании swift. </strong></p><p>вежливость <a href="https://medium.com/@yogevsitton/atomic-vs-non-atomic-properties-crash-course-d11c23f4366c">https://medium.com/@yogevsitton/atomic-vs-non-atomic-properties-crash-course-d11c23f4366c</a> </p>

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

<p><strong>атомные свойства</strong>: - когда переменная, назначенная с атомарным свойством, которое означает, что она имеет доступ только к одному потоку и будет поточно-ориентированной и будет хорошей с точки зрения производительности, будет иметь поведение по умолчанию.</p><p><strong>non atomic properties</strong>: - когда переменная, назначенная с атомарным свойством, которое означает, что она имеет многопоточный доступ и не будет потокобезопасной, будет медленной с точки зрения производительности, будет иметь поведение по умолчанию и когда два разных потока хотите получить доступ к переменной одновременно, это даст неожиданные результаты.</p>

<p>чтобы упростить всю путаницу, давайте разберемся с блокировкой мьютекса.</p><p>блокировка мьютекса, как следует из названия, блокирует изменчивость объекта. таким образом, если к объекту обращается класс, никакой другой класс не может получить доступ к тому же объекту.</p><p>в ios <code>@sychronise</code> также обеспечивает блокировку мьютекса. теперь он работает в режиме fifo и гарантирует, что на поток не влияют два класса, совместно использующие один и тот же экземпляр. однако, если задача находится в главном потоке, избегайте доступа к объекту с использованием атомарных свойств, так как это может задержать ваш пользовательский интерфейс и снизить производительность.</p>

<p>атомная: обеспечить безопасность потока, заблокировав поток с помощью nslock.</p><p>не атомарный: не обеспечивает безопасность потока, так как нет механизма блокировки потока.</p>

<p>правда в том, что они используют спин-блокировку для реализации атомарного свойства. код, как показано ниже:</p><pre><code> 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); } </code></pre>