it-swarm.com.de

Was ist der Unterschied zwischen den atomaren und den nichtatomaren Attributen?

Was bedeuten atomic und nonatomic in Eigenschaftsdeklarationen?

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

Was ist der betriebliche Unterschied zwischen diesen drei?

1770
Alex Wayne

Die letzten beiden sind identisch. "atomar" ist das Standardverhalten (beachten Sie, dass es sich eigentlich nicht um ein Keyword handelt. es wird nur durch das Fehlen von nonatomic angegeben - atomic wurde in den letzten Versionen von llvm/clang als Schlüsselwort hinzugefügt.

Wenn Sie davon ausgehen, dass Sie die Implementierungen der Methode @ synthetisieren, ändert atomarer und nicht atomarer Code den generierten Code. Wenn Sie Ihre eigenen Setter/Getter schreiben, sind atomare/nichtatomare/behalten/zuweisen/kopieren nur Ratschläge. (Hinweis: @synthesize ist jetzt das Standardverhalten in neueren Versionen von LLVM. Außerdem müssen Instanzvariablen nicht deklariert werden; sie werden ebenfalls automatisch synthetisiert und mit einem _ versehen, um einen versehentlichen direkten Zugriff zu verhindern.).

Mit "atomic" stellt der synthetisierte Setter/Getter sicher, dass ein ganze - Wert immer vom Getter zurückgegeben oder vom Setter gesetzt wird, unabhängig von der Setteraktivität in einem anderen Thread. Wenn sich Thread A in der Mitte des Getters befindet, während Thread B den Setter aufruft, wird ein tatsächlich realisierbarer Wert - am wahrscheinlichsten ein automatisch freigegebenes Objekt - an den Aufrufer in A zurückgegeben.

In nonatomic werden solche Garantien nicht gegeben. nonatomic ist also wesentlich schneller als "atomar".

Was "atomar" tut nicht macht, ist keine Garantie für die Gewindesicherheit. Wenn Thread A den Getter gleichzeitig aufruft, während Thread B und C den Setter mit unterschiedlichen Werten aufrufen, kann Thread A einen der drei Werte zurückgeben - den Wert, der vor dem Aufruf eines Setters oder eines der Werte, die in den Setter übergeben werden, zurückgegeben wird in B und C. Ebenso kann das Objekt mit dem Wert von B oder C enden, keine Möglichkeit zu sagen.

Die Gewährleistung der Datenintegrität - eine der Hauptherausforderungen der Multithreading-Programmierung - wird auf andere Weise erreicht.

Hinzufügen zu diesem:

atomicity einer einzelnen Eigenschaft kann auch keine Thread-Sicherheit gewährleisten, wenn mehrere abhängige Eigenschaften im Spiel sind.

Erwägen:

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

In diesem Fall könnte Thread A das Objekt umbenennen, indem Sie setFirstName: und dann setLastName: aufrufen. In der Zwischenzeit kann Thread B fullName zwischen den beiden Aufrufen von Thread A aufrufen und erhält den neuen Vornamen, der mit dem alten Nachnamen gekoppelt ist.

Um dies anzugehen, benötigen Sie ein Transaktionsmodell. Das heißt eine andere Art der Synchronisierung und/oder des Ausschlusses, die den Zugriff auf fullName ausschließen, während die abhängigen Eigenschaften aktualisiert werden.

1705
bbum

Dies wird in Apples documentation erklärt. Nachfolgend finden Sie einige Beispiele dafür, was tatsächlich passiert. Beachten Sie, dass es kein Schlüsselwort "atomic" gibt. Wenn Sie nicht "nonatomic" angeben, ist die Eigenschaft atomar. Wenn Sie jedoch "atomic" explizit angeben, wird ein Fehler ausgegeben.

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

- (UITextField *) userName {
    return userName;
}

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

Nun ist die atomare Variante etwas komplizierter:

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

Grundsätzlich muss die atomare Version eine Sperre einnehmen, um die Thread-Sicherheit zu gewährleisten, und die Referenzzählung für das Objekt (und die Autorelease-Zählung zum Ausgleich) so abwägen, dass das Objekt garantiert für den Aufrufer existiert, andernfalls dort ist eine potenzielle Race-Bedingung, wenn ein anderer Thread den Wert festlegt, wodurch der ref count auf 0 fällt.

Es gibt tatsächlich eine große Anzahl verschiedener Varianten, wie diese Dinge funktionieren, abhängig davon, ob es sich bei den Eigenschaften um skalare Werte oder Objekte handelt und wie die Eigenschaften keep, copy, readonly, nonatomic usw. interagieren. Im Allgemeinen wissen die Eigenschaftssynthesizer, wie sie für alle Kombinationen das "Richtige" tun.

350
Louis Gerbarg

Atomic

  • ist das Standardverhalten
  • stellt sicher, dass der aktuelle Prozess von der CPU abgeschlossen wird, bevor ein anderer Prozess auf die Variable zugreift
  • ist nicht schnell, da der Prozess vollständig abgeschlossen ist

Nicht-Atomic

  • ist NICHT das Standardverhalten
  • schneller (für synthetisierten Code, dh für Variablen, die mit @property und @synthesize erstellt wurden)
  • nicht fadensicher
  • kann zu unerwartetem Verhalten führen, wenn zwei verschiedene Prozesse gleichzeitig auf dieselbe Variable zugreifen
154
raw3d

Der beste Weg, den Unterschied zu verstehen, ist das folgende Beispiel. 

Angenommen, es gibt eine atomare Zeichenfolge-Eigenschaft namens "Name". Wenn Sie [self setName:@"A"] von Thread A aufrufen, [self setName:@"B"] von Thread B aufrufen und [self name] von Thread C aufrufen, werden alle Operationen für verschiedene Threads seriell ausgeführt, dh, wenn ein Thread vorhanden ist Wenn Sie einen Setter oder Getter ausführen, warten andere Threads.

Dies macht die Eigenschaft "name" Lese-/Schreibschutz sicher, aber wenn ein anderer Thread, D, gleichzeitig [name release] aufruft, kann dies zu einem Absturz führen, da hier kein Setter/Getter-Aufruf vorhanden ist. Dies bedeutet, dass ein Objekt schreibgeschützt (ATOMIC) ist, aber nicht threadsicher, da ein anderer Thread gleichzeitig beliebige Nachrichten an das Objekt senden kann. Der Entwickler sollte die Thread-Sicherheit für solche Objekte gewährleisten.

Wenn die Eigenschaft "name" nicht atomar war, werden alle Threads in obigem Beispiel - A, B, C und D gleichzeitig ausgeführt und erzeugen ein unvorhersehbares Ergebnis. Im Falle von Atomic wird entweder A, B oder C zuerst ausgeführt, D kann jedoch weiterhin parallel ausgeführt werden.

130
Vijayendra

Die Syntax und die Semantik sind bereits durch andere hervorragende Antworten auf diese Frage definiert. Da Ausführung und Leistung nicht genau beschrieben werden, füge ich meine Antwort hinzu.

Was ist der funktionale Unterschied zwischen diesen 3?

Ich hatte Atom als einen Standard immer als sehr neugierig betrachtet. Auf der Abstraktionsebene arbeiten wir daran, atomare Eigenschaften für eine Klasse als Fahrzeug zu verwenden, um eine Gewindesicherheit von 100% zu erreichen. Für wirklich korrekte Multithread-Programme ist ein Eingreifen des Programmierers mit großer Wahrscheinlichkeit eine Voraussetzung. Leistungsmerkmale und Ausführung wurden bisher noch nicht detailliert beschrieben. Nachdem ich im Laufe der Jahre einige stark multithreaded-Programme geschrieben hatte, hatte ich meine Eigenschaften die ganze Zeit als nonatomic deklariert, da Atomic für keinen Zweck sinnvoll war. Bei der Diskussion der Details atomarer und nichtatomarer Eigenschaften dieser Frage habe ich einige Profile gemacht, die auf einige merkwürdige Ergebnisse gestoßen sind.

Ausführung

OK. Als erstes möchte ich klarstellen, dass die Implementierung der Sperrung implementierungsdefiniert und abstrahiert ist. Louis verwendet @synchronized(self) in seinem Beispiel - ich habe dies als eine allgemeine Quelle der Verwirrung gesehen. Die Implementierung führt nicht zu tatsächlich use @synchronized(self); Es verwendet Objektebene Spin Locks. Louis 'Illustration eignet sich gut für eine übergeordnete Illustration mit Konstrukten, mit denen wir alle vertraut sind, aber es ist wichtig zu wissen, dass @synchronized(self) nicht verwendet wird.

Ein weiterer Unterschied besteht darin, dass atomare Eigenschaften Ihre Objekte innerhalb des Getters beibehalten/freigeben.

Leistung

Hier ist der interessante Teil: Die Leistung mit atomaren Eigenschaftszugriffen in uncontested -Fällen (z. B. Single-Threading) kann in einigen Fällen sehr schnell sein. In weniger als idealen Fällen kann die Verwendung von atomaren Zugriffen mehr als das 20-fache des Mehraufwands von nonatomic verursachen. Während der Fall Contested mit 7 Threads 44-mal langsamer war für die 3-Byte-Struktur (2,2 GHz Core i7 Quad-Core, x86_64). Die Drei-Byte-Struktur ist ein Beispiel für eine sehr langsame Eigenschaft.

Interessante Randnotiz: Benutzerdefinierte Accessoren der Drei-Byte-Struktur waren 52-mal schneller als die synthetisierten atomaren Accessoren; oder 84% der Geschwindigkeit von synthetisierten nichtatomaren Accessoren.

Objekte in umstrittenen Fällen können auch das 50-fache überschreiten.

Aufgrund der Anzahl von Optimierungen und Variationen bei Implementierungen ist es ziemlich schwierig, die Auswirkungen auf die reale Welt in diesen Kontexten zu messen. Sie hören oft etwas wie "Vertrauen Sie ihr, wenn Sie kein Profil haben und feststellen, dass es ein Problem ist". Aufgrund des Abstraktionsniveaus ist es tatsächlich ziemlich schwierig, die tatsächlichen Auswirkungen zu messen. Das Ablesen der tatsächlichen Kosten von Profilen kann sehr zeitaufwändig sein und aufgrund von Abstraktionen ziemlich ungenau sein. ARC vs. MRC kann ebenfalls einen großen Unterschied machen.

Lassen Sie uns also einen Schritt zurückgehen, nicht auf die Implementierung von Eigenschaftszugriffen fokussieren. Wir schließen die üblichen Verdächtigen wie objc_msgSend ein und untersuchen einige realistische Ergebnisse auf hoher Ebene für viele Aufrufe eines NSString getter in unbestritten Fälle (Werte in Sekunden):

  • MRC | nichtatomisch | manuell implementierte Getter: 2
  • MRC | nichtatomisch | synthetisierter Getter: 7
  • MRC | atomar | synthetisierter Getter: 47
  • ARC | nichtatomisch | synthetisierter Getter: 38 (Anmerkung: ARC fügt hier den Zählerstand hinzu)
  • ARC | atomar | synthetisierter Getter: 47

Wie Sie wahrscheinlich bereits vermutet haben, leistet die Referenzzähleraktivität/-zyklus einen bedeutenden Beitrag bei Atomic und unter ARC. Sie würden auch größere Unterschiede in umstrittenen Fällen feststellen.

Obwohl ich sehr auf die Leistung achte, sage ich trotzdem Semantics First!. Mittlerweile hat Leistung bei vielen Projekten eine geringe Priorität. Die Ausführungsdetails und -kosten der von Ihnen verwendeten Technologien zu kennen, schadet jedoch nicht. Sie sollten die richtige Technologie für Ihre Bedürfnisse, Zwecke und Fähigkeiten verwenden. Hoffentlich ersparen Sie sich damit einige Stunden Vergleiche und helfen Ihnen beim Treffen Ihrer Programme, eine fundiertere Entscheidung zu treffen.

109
justin

Atomic = Gewindesicherheit

Nicht-atomar = Keine Gewindesicherheit

Fadensicherheit:

Instanzvariablen sind threadsicher, wenn sie sich beim Zugriff von mehreren Threads korrekt verhalten, unabhängig von der Planung oder Verschachtelung der Ausführung dieser Threads durch die Laufzeitumgebung und ohne zusätzliche Synchronisation oder sonstige Koordination seitens des aufrufenden Codes.

In unserem Zusammenhang:

Wenn ein Thread den Wert der Instanz ändert, ist der geänderte Wert für alle Threads verfügbar, und nur ein Thread kann den Wert gleichzeitig ändern.

Wo Sie atomic verwenden:

wenn auf die Instanzvariable in einer Multithread-Umgebung zugegriffen wird.

Implikation von atomic:

Nicht so schnell wie nonatomic, da nonatomic von der Laufzeit aus keine Watchdog-Arbeit erfordert.

Wo Sie nonatomic verwenden:

Wenn die Instanzvariable nicht von mehreren Threads geändert wird, können Sie sie verwenden. Es verbessert die Leistung.

92
Durai Amuthan.H

Ich fand eine ziemlich gute Erklärung für atomare und nichtatomare Eigenschaften hier . Hier ist ein relevanter Text aus dem gleichen:

'atomar' bedeutet, dass es nicht zerlegt werden kann. Unter OS/Programmierung versteht man einen atomaren Funktionsaufruf, der nicht unterbrochen werden kann. Die gesamte Funktion muss ausgeführt werden und darf nicht durch die normale Kontextumschaltung der OS aus der CPU ausgelagert werden, bis sie abgeschlossen ist. Nur für den Fall, dass Sie nicht wussten: Da die CPU jeweils nur eine Aufgabe ausführen kann, dreht das Betriebssystem den Zugriff auf die CPU in kleinen Zeitabschnitten auf alle laufenden Prozesse, um die Illusion zu erzeugen von Multitasking. Der CPU-Scheduler kann (und tut) einen Prozess zu jedem Zeitpunkt seiner Ausführung unterbrechen - auch während eines Funktionsaufrufs. Für Aktionen wie das Aktualisieren gemeinsam genutzter Zählervariablen, bei denen zwei Prozesse versuchen könnten, die Variable gleichzeitig zu aktualisieren, müssen sie also "atomar" ausgeführt werden, dh, jede Aktualisierungsaktion muss vollständig abgeschlossen sein, bevor ein anderer Prozess auf den Server übertragen werden kann ZENTRALPROZESSOR.

Ich würde also vermuten, dass atomar in diesem Fall bedeutet, dass die Attribut-Reader-Methoden nicht unterbrochen werden können. Dies bedeutet, dass die von der Methode gelesenen Variablen ihren Wert nicht auf halbem Weg ändern können, da ein anderer Thread/Aufruf/eine andere Funktion abgerufen wird auf die CPU getauscht.

Da die Variablen atomic nicht unterbrochen werden können, ist der von ihnen enthaltene Wert zu jedem Zeitpunkt (thread-lock) garantiert unbeschädigt . Wenn Sie jedoch sicherstellen, dass diese Thread-Sperre aktiviert ist, wird der Zugriff auf sie langsamer. non-atomic -Variablen geben dagegen keine Garantie, bieten aber den Luxus eines schnelleren Zugriffs. Um es zusammenzufassen, fahren Sie mit non-atomic fort, wenn Sie wissen, dass nicht mehrere Threads gleichzeitig auf Ihre Variablen zugreifen können, und beschleunigen Sie die Schritte.

68
tipycalFlow

Nachdem ich so viele Artikel gelesen und Stack Overflow veröffentlicht und Demo-Anwendungen zur Prüfung der Attributeigenschaften von Variablen erstellt hatte, entschied ich mich, alle Attributinformationen zusammenzustellen:

  1. atomic/ Standardeinstellung
  2. nonatomic
  3. strong = retain // Standardeinstellung
  4. weak = unsafe_unretained
  5. retain
  6. assign // Standardeinstellung
  7. unsafe_unretained
  8. copy
  9. readonly
  10. readwrite // Standardeinstellung

Im Artikel _/Variableneigenschaftsattribute oder -modifizierer in iOS finden Sie alle oben genannten Attribute, und das wird Ihnen definitiv helfen.

  1. atomic

    • atomic bedeutet, dass nur ein Thread auf die Variable zugreift (statischer Typ).
    • atomic ist threadsicher.
    • Die Leistung ist jedoch langsam
    • atomic ist das Standardverhalten
    • Atomare Accessoren in einer Umgebung, in der keine Abfälle gesammelt wurden (d. H. Bei Verwendung von keep/release/autorelease), verwenden eine Sperre, um sicherzustellen, dass ein anderer Thread die korrekte Einstellung/das korrekte Abrufen des Werts nicht beeinträchtigt.
    • Es ist eigentlich kein Schlüsselwort. 

    Beispiel:

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

    • nonatomic bedeutet, dass mehrere Threads auf die Variable zugreifen (dynamischer Typ).
    • nonatomic ist Thread-unsicher.
    • Aber es ist schnell in der Leistung
    • nonatomic ist NICHT das Standardverhalten. Wir müssen das Schlüsselwort nonatomic im Eigenschaftsattribut hinzufügen.
    • Dies kann zu unerwartetem Verhalten führen, wenn zwei unterschiedliche Prozesse (Threads) gleichzeitig auf dieselbe Variable zugreifen. 

    Beispiel:

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

Atomic:

Atomic garantiert, dass der Zugriff auf die Immobilie atomar erfolgt. Z.B. Es werden immer vollständig initialisierte Objekte zurückgegeben. Jedes Get/Set einer Eigenschaft in einem Thread muss abgeschlossen sein, bevor ein anderer darauf zugreifen kann.

Wenn Sie sich vorstellen, dass die folgende Funktion auf zwei Threads gleichzeitig auftritt, können Sie sehen, warum die Ergebnisse nicht hübsch sind.

-(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;
  }

  ...
}

Vorteile: Die Rückgabe vollständig initialisierter Objekte macht es bei Multithreading zur besten Wahl.

Nachteile: Leistungstreffer, macht die Ausführung etwas langsamer

Nicht-Atomic:

Im Gegensatz zu Atomic kann nicht jedes Mal eine vollständig initialisierte Objektrückgabe sichergestellt werden.

Pros: Extrem schnelle Ausführung.

Nachteile: Chancen für den Müllwert bei Multithreading.

52
Andrew Grant

Die einfachste Antwort zuerst: Es gibt keinen Unterschied zwischen Ihren zweiten beiden Beispielen. Standardmäßig sind Eigenschaftszugriffe atomar.

Atomare Accessoren in einer Umgebung, in der keine Abfälle gesammelt wurden (d. H. Bei Verwendung von keep/release/autorelease), verwenden eine Sperre, um sicherzustellen, dass ein anderer Thread die korrekte Einstellung/das korrekte Abrufen des Werts nicht beeinträchtigt.

Weitere Informationen und weitere Hinweise zum Erstellen von Multithread-Apps finden Sie im Abschnitt " Leistung und Threading " der Dokumentation Objective-C 2.0 von Apple.

52
Jay O'Conor

Atomic bedeutet, dass nur ein Thread auf die Variable zugreift (statischer Typ). Atomic ist Thread-sicher, aber langsam.

Nichtatomisch bedeutet, dass mehrere Threads auf die Variable zugreifen (dynamischer Typ). Nichtatomisch ist Thread-unsicher, aber es ist schnell.

31
IOS Rocks

Atomic ist thread safe, es ist slow und wells versichert (nicht garantiert), dass nur der gesperrte Wert angegeben wird, unabhängig davon, wie viele Threads über dieselbe Zone zugreifen. Wenn Sie atomar verwenden, wird ein in diese Funktion geschriebener Code zu einem Teil des kritischen Abschnitts, zu dem jeweils nur ein Thread ausgeführt werden kann.

Es gewährleistet nur die Gewindesicherheit; es garantiert das nicht. Was ich damit meine, ist, dass Sie einen erfahrenen Fahrer für Ihr Auto anstellen, aber es garantiert nicht, dass das Auto keinen Unfall hat. Die Wahrscheinlichkeit bleibt jedoch die geringste.

Atomic - es kann nicht zerlegt werden, daher wird das Ergebnis erwartet. Bei nonatomic - Wenn ein anderer Thread auf die Speicherzone zugreift, kann er diese ändern, sodass das Ergebnis unerwartet ist.

Code Talk: 

Atomischer Get-Getter und Setter des Property-Threads sicher. zum Beispiel, wenn Sie geschrieben haben: 

self.myProperty = value;

ist threadsicher. 

[myArray addObject:@"Abc"] 

ist NICHT threadsicher. 

14
user3693546

Es gibt kein solches Schlüsselwort "atomar"

@property(atomic, retain) UITextField *userName;

Wir können das obige gerne verwenden

@property(retain) UITextField *userName;

Siehe Stapelüberlauf-Frage Ich bekomme Probleme, wenn ich @property (atomic, keep) NSString * myString verwende.

12
Deepak

Das default ist atomic, das heißt, es kostet Sie Leistung, wenn Sie die Eigenschaft verwenden, aber es ist threadsicher. Was Objective-C tut, ist eine Sperre, sodass nur der tatsächliche Thread auf die Variable zugreifen kann, solange der Setter/Getter ausgeführt wird. 

Beispiel mit MRC einer Eigenschaft mit einem ivar _internal:

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

Die letzten beiden sind also gleich:

@property(atomic, retain) UITextField *userName;

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

Auf der anderen Seite fügt nonatomic nichts zu Ihrem Code hinzu. Es ist also nur fadensicher, wenn Sie den Sicherheitsmechanismus selbst codieren.

@property(nonatomic, retain) UITextField *userName;

Die Schlüsselwörter müssen überhaupt nicht als erstes Eigenschaftsattribut geschrieben werden.

Vergiss nicht, das bedeutet nicht, dass die Eigenschaft insgesamt Thread-sicher ist. Nur der Methodenaufruf des Setter/Getters ist. Wenn Sie jedoch einen Setter und danach einen Getter gleichzeitig mit 2 verschiedenen Threads verwenden, könnte dieser ebenfalls beschädigt werden!

11
Binarian

atomar (Standard)

Atomic ist die Standardeinstellung: Wenn Sie nichts eingeben, lautet Ihre Eigenschaft atomar. Eine atomare Eigenschaft ist garantiert, wenn Sie versuchen, aus .__ zu lesen. Dann erhalten Sie einen gültigen Wert zurück. Es gibt keine Garantien was der Wert sein könnte, aber Sie erhalten gute Daten zurück, nicht nur Junk-Speicher. Sie können dies tun, wenn Sie mehrere Threads oder mehrere Prozesse, die auf eine einzige Variable zeigen, eine Thread kann lesen und ein anderer Thread kann schreiben. Wenn sie gleichzeitig schlagen Zu diesem Zeitpunkt erhält der Reader-Thread garantiert einen der beiden Werte: entweder vor der Änderung oder nach der Änderung. Was atomar nicht tut Ihnen geben Sie eine Garantie dafür, welche dieser Werte Sie haben vielleicht bekommen. Atomic wird in der Regel mit Thread-sicherem .__ verwechselt. und das stimmt nicht. Sie müssen Ihre Thread-Sicherheit gewährleisten andere Möglichkeiten. Atomic garantiert jedoch, dass .__, wenn Sie versuchen zu lesen. Sie erhalten einen Wert zurück.

nichtatomisch

Auf der anderen Seite bedeutet nicht-atomar, wie Sie wahrscheinlich vermuten können, nur „Mach das nicht atomare Sachen.“ Was du verlierst, ist die Garantie, dass du Immer etwas zurückbekommen. Wenn Sie versuchen, mitten in einem .__ zu lesen. schreiben, könnten Sie Mülldaten zurückbekommen. Andererseits gehen Sie. ein bisschen schneller. Weil atomare Eigenschaften etwas Magisches bewirken müssen Um zu garantieren, dass Sie einen Wert zurückbekommen, sind sie etwas langsamer. Ob Es ist eine Eigenschaft, auf die Sie häufig zugreifen, Sie möchten .__ löschen. auf nichtatomisch, um sicherzustellen, dass Sie diese Geschwindigkeit nicht erreichen Strafe.

Mehr dazu hier: https://realm.io/news/tmi-objective-c-property-attributes/

9
Proton

Bevor Sie beginnen: Sie müssen wissen, dass jedes Objekt im Speicher freigegeben werden muss, damit ein neuer Writer ausgeführt werden kann. Sie können nicht einfach auf etwas schreiben, wie Sie es auf Papier tun. Sie müssen es zuerst löschen (freigeben) und dann können Sie darauf schreiben. Wenn in dem Moment, in dem der Löschvorgang abgeschlossen ist (oder die Hälfte abgeschlossen ist) und noch nichts geschrieben wurde (oder die Hälfte geschrieben wurde) und Sie versuchen, es lesen könnten sei sehr problematisch! Atomic und Nonatomic helfen Ihnen, dieses Problem auf verschiedene Arten zu behandeln.

Lesen Sie zuerst this question und dann Bbums Antwort . Lesen Sie außerdem dann meine Zusammenfassung.


atomic garantiert IMMER

  • Wenn zwei verschiedene Personen gleichzeitig lesen und schreiben möchten, brennt Ihr Papier nicht nur! -> Ihre Anwendung wird auch unter Rennbedingungen niemals abstürzen.
  • Wenn eine Person versucht zu schreiben und nur 4 der 8 zu schreibenden Buchstaben geschrieben hat, dann kann kein in der Mitte lesen, das Lesen kann nur durchgeführt werden, wenn alle 8 Buchstaben geschrieben sind -> Es wird kein Lesen (Erhalten) am stattfinden "Ein Thread, der noch schreibt", dh, wenn 8 Byte in Byte geschrieben werden müssen und nur 4 Byte geschrieben werden - bis zu diesem Zeitpunkt dürfen Sie nicht aus diesem Thread lesen. Aber da ich sagte, dass es nicht abstürzt, würde es aus dem Wert eines autoreleased Objekts lesen.
  • Wenn Sie vor dem Schreiben das zuvor auf Papier Geschriebene gelöscht haben und dann will dir jemand vorlesen kann noch vorlesen. Wie? Sie lesen von etwas ähnlichem wie dem Mac OS-Papierkorb (da der Papierkorb noch nicht zu 100% gelöscht ist ... er ist in einer Schwebe) ---> Wenn ThreadA lesen soll, während ThreadB bereits die Zuordnung zum Schreiben aufgehoben hat, erhalten Sie Ein Wert aus dem endgültigen vollständig geschriebenen Wert von ThreadB oder etwas aus dem Autorelease-Pool.

Beibehaltungszähler sind die Art und Weise, wie Speicher in Objective-C verwaltet wird. Wenn Sie ein Objekt erstellen, hat es eine Aufbewahrungszahl von 1. Wenn Sie einem Objekt eine Aufbewahrungsnachricht senden, wird die Aufbewahrungszahl um 1 erhöht. Wenn Sie einem Objekt eine Freigabemeldung senden, wird die Aufbewahrungszahl um 1 verringert Senden Sie einem Objekt eine Autorelease-Nachricht , deren Anzahl der Aufbewahrungen zu einem späteren Zeitpunkt um 1 verringert wird. Wenn der Aufbewahrungszähler eines Objekts auf 0 reduziert wird, wird die Zuordnung aufgehoben.

  • Atomic garantiert nicht die Thread-Sicherheit, obwohl dies nützlich ist, um die Thread-Sicherheit zu erreichen. Die Thread-Sicherheit hängt davon ab, wie Sie Ihren Code schreiben/aus welcher Thread-Warteschlange Sie lesen/schreiben. Es wird nur ein nicht absturzfähiges Multithreading garantiert.

Was ?! Sind Multithreading und Thread-Sicherheit unterschiedlich?

Ja. Multithreading bedeutet: Mehrere Threads können ein gemeinsam genutztes Datenelement gleichzeitig lesen und wir werden nicht abstürzen, es kann jedoch nicht garantiert werden, dass Sie nicht von einem nicht automatisch freigegebenen Wert lesen. Mit der Thread-Sicherheit wird garantiert, dass das, was Sie lesen, nicht automatisch freigegeben wird. Der Grund, warum wir nicht standardmäßig alles atomar machen, ist, dass es Leistungskosten gibt und für die meisten Dinge keine wirkliche Threadsicherheit erforderlich ist. Einige Teile unseres Codes benötigen diesen Code, und für diese wenigen Teile müssen wir unseren Code threadsicher mithilfe von Sperren, Mutex oder Synchronisierung schreiben.


nonatomic

  • Da es keinen Papierkorb für Mac OS gibt, interessiert es niemanden, ob Sie immer einen Wert erhalten (<- Dies könnte möglicherweise zu einem Absturz führen) oder ob es jemanden interessiert, wenn jemand versucht, in der Mitte Ihres Schreibvorgangs zu lesen (obwohl) Die Hälfte des Schreibens im Speicher unterscheidet sich stark von der Hälfte des Schreibens auf Papier. Auf dem Speicher können Sie einen verrückten, dummen Wert aus der Vergangenheit finden, während Sie auf dem Papier nur die Hälfte des Geschriebenen sehen. -> Garantiert nicht, dass Sie nicht abstürzen, weil Es wird kein Autorelease-Mechanismus verwendet.
  • Gewährleistet nicht, dass vollständige schriftliche Werte gelesen werden!
  • Ist schneller als atomar

Insgesamt unterscheiden sie sich in 2 Aspekten:

  • Absturz oder nicht aufgrund eines Autorelease-Pools.

  • Das Lesen direkt in der Mitte eines 'noch nicht beendeten Schreibens oder leeren Werts' erlauben oder nicht erlauben und nur lesen, wenn der Wert vollständig geschrieben ist.

9
Honey

Wenn Sie Ihre Eigenschaft in Multithread-Code verwenden, können Sie den Unterschied zwischen nichtatomaren und atomaren Attributen erkennen. Nonatomic ist schneller als atomar und atomar ist fadensicher und nicht atomar.

Vijayendra Tripathi hat bereits ein Beispiel für eine Multithread-Umgebung gegeben.

8
Ankul Gaur
  • -Atomic bedeutet, dass nur ein Thread auf die Variable zugreift (statischer Typ).
  • -Atomic ist Thread-sicher.
  • -aber die Leistung ist langsam

Wie erkläre ich:

Da Atom standardmäßig ist,

@property (retain) NSString *name;

UND in der Implementierungsdatei

self.name = @"sourov";

Angenommen, eine Aufgabe, die sich auf drei Eigenschaften bezieht, ist

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

Alle Eigenschaften arbeiten parallel (asynchron). 

Wenn Sie "Name" aus dem Thread A aufrufen, 

Und 

Zur gleichen Zeit, wenn Sie anrufen 

[self setName:@"Datta"]

aus dem Thread B

Now Wenn die * name -Eigenschaft nicht atomar ist, dann 

  • Es wird der Wert "Datta" für A zurückgegeben
  • Es wird der Wert "Datta" für B zurückgegeben

Aus diesem Grund wird Nicht-Atom als Thread unsicher bezeichnet. Aufgrund der parallelen Ausführung ist die Leistung jedoch schnell. 

Now If * name -Eigenschaft ist atomar

  • Es wird den Wert "Sourov" für A sicherstellen
  • Dann wird der Wert "Datta" für B zurückgegeben

Deshalb heißt atomic threadsicher und deshalb heißt es schreibgeschützt

Eine solche Situation wird seriell durchgeführt. Und langsam in der Leistung

- Nonatomic bedeutet, dass mehrere Threads auf die Variable zugreifen (dynamischer Typ).

- Nichtatomisch ist Thread unsicher.

- aber es ist schnell in der Leistung

-Nonatomic ist NICHT Standardverhalten, wir müssen ein nichtatomisches Schlüsselwort im Eigenschaftsattribut hinzufügen.

Für In Swift Bestätigung, dass die Swift-Eigenschaften im ObjC-Sinn nicht atomar sind. Ein Grund ist, dass Sie darüber nachdenken, ob die Atomizität pro Eigenschaft für Ihre Bedürfnisse ausreichend ist.

Referenz: https://forums.developer.Apple.com/thread/25642

Weitere Informationen finden Sie auf der Website http://rdcworld-iphone.blogspot.in/2012/12/variable-property-attributes-or.html

8
Shourob Datta

Bevor Sie sich mit den Attributen von @property befassen, sollten Sie wissen, wie @property verwendet wird. @property bietet eine Möglichkeit, die Informationen zu definieren, die eine Klasse kapseln soll. Wenn Sie ein Objekt/eine Variable mit @property deklarieren, können andere Klassen auf dieses Objekt/diese Variable zugreifen, die ihre Klasse importieren. Wenn Sie ein Objekt mit @property in der Header-Datei deklarieren, müssen Sie es mit @synthesize in der Implementierungsdatei synthetisieren.

Beispiel:

.h Klasse

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

.m Klasse

@implementation ExampleClass
   @synthesize name;
@end

Nun synthetisiert der Compiler die Zugriffsmethoden für name.

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

Liste der Attribute von @property: atomic. nichtatomar. behalten. Kopieren. schreibgeschützt. lesen Schreiben. zuordnen. stark.

atomar: Dies ist das Standardverhalten. Wenn ein Objekt als atomar deklariert wird, ist es threadsicher. Thread-sicher bedeutet, dass zu einem Zeitpunkt nur ein Thread einer bestimmten Instanz dieser Klasse die Kontrolle über dieses Objekt haben kann.

Beispiel

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

nichtatomar: Es ist nicht threadsicher. Mit dem Attribut "nonatomic property" können Sie festlegen, dass synthetisierte Accessoren einen Wert einfach festlegen oder direkt zurückgeben. Dabei können Sie nicht garantieren, was passiert, wenn auf denselben Wert gleichzeitig von verschiedenen Threads aus zugegriffen wird. Aus diesem Grund ist der Zugriff auf eine nichtatomare Eigenschaft schneller als auf eine atomare. @property (nonatomic)NSString *name;

beibehalten: Wird benötigt, wenn das Attribut ein Zeiger auf ein Objekt ist. Die Setter-Methode erhöht die Anzahl der Beibehaltungen des Objekts, sodass der Speicher im Autorelease-Pool belegt wird. @property (retain)NSString *name;

kopieren: Wenn Sie Kopieren verwenden, können Sie Retain nicht verwenden. Bei Verwendung der Instanz copy der Klasse wird eine eigene Kopie erstellt. Selbst wenn eine veränderbare Zeichenfolge festgelegt und anschließend geändert wird, erfasst die Instanz den Wert, den sie zum Zeitpunkt der Festlegung hat. Es werden keine Setter- und Getter-Methoden synthetisiert.

@property (copy) NSString *name;

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

readonly: Wenn Sie nicht zulassen möchten, dass die Eigenschaft über die Setter-Methode geändert wird, können Sie die Eigenschaft readonly deklarieren. @property (readonly) NSString *name;

readwrite: ist das Standardverhalten. Sie müssen das Attribut readwrite nicht explizit angeben.

@property (readwrite) NSString *name;

assign: Erzeugt einen Setter, der der Instanzvariablen den Wert direkt zuweist, anstatt ihn zu kopieren oder beizubehalten. Dies ist am besten für primitive Typen wie NSInteger und CGFloat oder Objekte geeignet, die Sie nicht direkt besitzen, z. B. Delegaten.

@property (assign) NSInteger year;

stark: ist ein Ersatz für behalten. @property (nonatomic, strong) AVPlayer *player;

unsafe_unretained: In Cocoa und Cocoa Touch gibt es einige Klassen, die noch keine schwachen Referenzen unterstützen. Sie können also keine schwachen Eigenschaften oder lokale Variablen deklarieren, um den Überblick zu behalten. Diese Klassen umfassen NSTextView, NSFont und NSColorSpace usw. Wenn Sie einen schwachen Verweis auf eine dieser Klassen verwenden müssen, müssen Sie einen unsicheren Verweis verwenden. Eine unsichere Referenz ähnelt einer schwachen Referenz, da sie das zugehörige Objekt nicht am Leben erhält, jedoch nicht auf null gesetzt wird, wenn die Zuordnung des Zielobjekts aufgehoben wird.

@property (unsafe_unretained) NSObject *unsafeProperty;

8
Varun Naharia

Die atomare Eigenschaft stellt sicher, dass ein vollständig initialisierter Wert beibehalten wird, unabhängig davon, wie viele Threads Getter & Setter darauf ausführen. 

Die Eigenschaft "Nichtatomisch" gibt an, dass synthetisierte Zugriffsmethoden einen Wert einfach direkt festlegen oder zurückgeben. Es kann nicht garantiert werden, was passiert, wenn auf denselben Wert gleichzeitig von verschiedenen Threads zugegriffen wird.

4
Laxman Sahni

Atomic bedeutet, dass jeweils nur ein Thread auf die Variable zugreifen kann (statischer Typ). Atomic ist Thread-sicher, aber langsam.

Nichtatomisch bedeutet, dass mehrere Threads gleichzeitig auf die Variable zugreifen können (dynamischer Typ). Nichtatomisch ist Thread-unsicher, aber es ist schnell.

3
Kemo

Wenn Sie Atomic verwenden, bedeutet dies, dass der Thread sicher und schreibgeschützt ist. Wenn Sie nonatomic verwenden, bedeutet dies, dass mehrere Threads auf die Variable zugreifen und Thread-unsicher ist. Sie wird jedoch schnell ausgeführt und führt Lese- und Schreibvorgänge aus. Dies ist ein dynamischer Typ.

2
Preetha

Atomic properties : - Wenn eine mit einer atomischen Eigenschaft zugewiesene Variable bedeutet, dass sie nur einen Threadzugriff hat und Thread-sicher ist und in der Leistungsperspektive gut ist, hat dies ein Standardverhalten.

Nicht-atomare Eigenschaften : - Wenn eine mit einer atomischen Eigenschaft zugewiesene Variable bedeutet, dass sie über einen Multithreadzugriff verfügt und nicht threadsicher ist und in der Leistungsperspektive langsam ist, das Standardverhalten und wenn zwei verschiedene Threads zugreifen möchten Variable zur gleichen Zeit gibt es unerwartete Ergebnisse.

0
ashish.surana

Atomicity Atomic (Standard)

Atomic ist die Standardeinstellung: Wenn Sie nichts eingeben, ist Ihre Eigenschaft atomar. Es wird garantiert, dass eine atomare Eigenschaft einen gültigen Wert zurückgibt, wenn Sie versuchen, daraus zu lesen. Es gibt keine Garantie dafür, was dieser Wert sein könnte, aber Sie erhalten gute Daten zurück, nicht nur Junk-Speicher. Wenn Sie über mehrere Threads oder mehrere Prozesse verfügen, die auf eine einzige Variable zeigen, kann ein Thread lesen und ein anderer Thread schreiben. Wenn sie gleichzeitig treffen, erhält der Leser-Thread garantiert einen der beiden Werte: entweder vor der Änderung oder nach der Änderung. Was atomar Ihnen nicht gibt, ist eine Garantie dafür, welche dieser Werte Sie erhalten könnten. Atomic wird im Allgemeinen mit Thread-sicher verwechselt, und das ist nicht richtig. Sie müssen Ihre Threadsicherheit auf andere Weise garantieren. Atomic garantiert jedoch, dass Sie beim Lesen wieder einen Wert erhalten.

nichtatomisch

Auf der anderen Seite bedeutet nicht-atomar, wie Sie wahrscheinlich vermuten können, nur: „Tun Sie nichts Atomisches.“ Was Sie verlieren, ist die Garantie, dass Sie immer etwas zurückbekommen. Wenn Sie versuchen, während eines Schreibvorgangs zu lesen, erhalten Sie möglicherweise Mülldaten zurück. Andererseits geht man ein bisschen schneller. Da atomare Eigenschaften eine gewisse Magie erfordern, um sicherzustellen, dass Sie einen Wert zurückerhalten, sind sie etwas langsamer. Wenn es sich um eine Eigenschaft handelt, auf die Sie häufig zugreifen, möchten Sie möglicherweise auf Nichtatomisch zurückgreifen, um sicherzustellen, dass Sie nicht diese Geschwindigkeitsstrafe einnehmen

mit freundlicher Genehmigung https://academy.realm.io/posts/tmi-objective-c-property-attributes/

Atomicity-Eigenschaftsattribute (atomar und nichtatomisch) werden in der entsprechenden Swift-Eigenschaftendeklaration nicht berücksichtigt. Die Atomitätsgarantien der Objective-C-Implementierung gelten jedoch weiterhin, wenn auf die importierte Eigenschaft über Swift zugegriffen wird.

Also - wenn Sie eine atomare Eigenschaft in Objective-C definieren, bleibt sie bei Verwendung von Swift atomar.

courtesy https://medium.com/@YogevSitton/atomic-vs-non-atomic-properties-crash-course-d11c23f4366c

0
Suraj K Thomas

Um die gesamte Verwirrung zu vereinfachen, lassen Sie uns die Mutex-Sperre verstehen.

Die Mutex-Sperre sperrt die Namensveränderlichkeit des Objekts. Wenn also auf eine Klasse auf das Objekt zugegriffen wird, kann keine andere Klasse auf dasselbe Objekt zugreifen.

In iOS stellt @sychronise auch die Mutex-Sperre bereit. Jetzt dient sie im Modus FIFO und stellt sicher, dass der Fluss nicht von zwei Klassen beeinflusst wird, die dieselbe Instanz verwenden. Wenn sich die Task jedoch im Hauptthread befindet, vermeiden Sie den Zugriff auf Objekte mit atomaren Eigenschaften, da dies Ihre Benutzeroberfläche halten und die Leistung beeinträchtigen kann.

0

Atomic: Gewährleisten Sie die Thread-Sicherheit, indem Sie den Thread mit NSLOCK sperren.

Nicht atomar: Gewährleistet keine Thread-Sicherheit, da es keinen Thread-Verriegelungsmechanismus gibt.

0
satisharyan

Die Wahrheit ist, dass sie Spin-Lock verwenden, um atomare Eigenschaften zu implementieren. Der Code wie folgt:

 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
paul