Die Syntax und Semantik sind bereits durch andere hervorragende Antworten auf diese Frage gut definiert. Da Ausführung und Leistung nicht gut detailliert sind, werde ich meine Antwort hinzufügen.
Was ist der funktionale Unterschied zwischen diesen 3?
Ich hatte Atomic immer als Standard angesehen, ziemlich neugierig. Auf der Abstraktionsebene, auf der wir arbeiten, ist die Verwendung atomarer Eigenschaften für eine Klasse als Vehikel zur Erzielung einer 100% igen Thread-Sicherheit ein Eckfall. Für wirklich korrekte Multithread-Programme ist mit ziemlicher Sicherheit ein Eingreifen des Programmierers erforderlich. In der Zwischenzeit wurden Leistungsmerkmale und Ausführung noch nicht detailliert beschrieben. Nachdem ich im Laufe der Jahre einige stark multithreaded Programme geschrieben hatte, hatte ich meine Eigenschaften als nonatomic
die ganze Zeit deklariert, weil Atomic für keinen Zweck sinnvoll war. Während der Diskussion der Details der atomaren und nichtatomaren Eigenschaften dieser Frage stieß ich bei einigen Profilen auf einige merkwürdige Ergebnisse.
Ausführung
OK. Als erstes möchte ich klarstellen, dass die Sperrimplementierung implementierungsdefiniert und abstrahiert ist. Louis verwendet @synchronized(self)
in seinem Beispiel - ich habe dies als eine häufige Quelle der Verwirrung gesehen. Die Implementierung ist nicht tatsächlich verwenden @synchronized(self)
; Es werden Spin-Sperren auf Objektebene verwendet . Louis 'Illustration ist gut für eine hochrangige Illustration mit Konstrukten, mit denen wir alle vertraut sind, aber es ist wichtig zu wissen, dass sie nicht verwendet wird @synchronized(self)
.
Ein weiterer Unterschied besteht darin, dass die atomaren Eigenschaften Ihre Objekte im Getter beibehalten / freigeben.
Performance
Hier ist der interessante Teil: Die Leistung bei der Verwendung von atomaren Eigenschaftszugriffen in unbestrittenen Fällen (z. B. Single-Threaded-Fällen) 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 Overheads kosten nonatomic
. Während der umstrittene Fall mit 7 Threads für die Drei-Byte-Struktur (2,2 GHz Core i7 Quad Core, x86_64) 44-mal langsamer war . 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 Atom-Accessoren; oder 84% der Geschwindigkeit synthetisierter nichtatomarer Accessoren.
Objekte in umstrittenen Fällen können auch das 50-fache überschreiten.
Aufgrund der Anzahl der Optimierungen und Variationen bei den Implementierungen ist es ziemlich schwierig, die tatsächlichen Auswirkungen in diesen Kontexten zu messen. Möglicherweise hören Sie häufig etwas wie "Vertrauen Sie ihm, es sei denn, Sie profilieren und stellen fest, dass es ein Problem ist". Aufgrund der Abstraktionsebene ist es tatsächlich ziemlich schwierig, die tatsächlichen Auswirkungen zu messen. Das Abrufen der tatsächlichen Kosten aus Profilen kann sehr zeitaufwändig und aufgrund von Abstraktionen sehr ungenau sein. Auch ARC vs MRC können einen großen Unterschied machen.
Lassen Sie uns also einen Schritt zurücktreten und uns nicht auf die Implementierung von Eigenschaftszugriffen konzentrieren. Wir werden die üblichen Verdächtigen wie einbeziehen objc_msgSend
und einige reale High-Level-Ergebnisse für viele Aufrufe eines NSString
Getters in unbestrittenen Fällen untersuchen (Werte in Sekunden):
- MRC | nichtatomar | manuell implementierte Getter: 2
- MRC | nichtatomar | synthetisierter Getter: 7
- MRC | atomar | synthetisierter Getter: 47
- ARC | nichtatomar | synthetisierter Getter: 38 (Hinweis: ARC fügt hier Ref Count Count hinzu)
- ARC | atomar | synthetisierter Getter: 47
Wie Sie wahrscheinlich erraten haben, trägt die Aktivität / das Radfahren der Referenzzählung wesentlich zur Atomik und unter ARC bei. Sie würden auch größere Unterschiede in umstrittenen Fällen sehen.
Obwohl ich der Leistung große Aufmerksamkeit schenke, sage ich immer noch Semantik zuerst! . In der Zwischenzeit hat die Leistung für viele Projekte eine niedrige Priorität. Die Kenntnis der Ausführungsdetails und der Kosten der von Ihnen verwendeten Technologien schadet jedoch sicherlich nicht. Sie sollten die richtige Technologie für Ihre Bedürfnisse, Zwecke und Fähigkeiten verwenden. Dies erspart Ihnen hoffentlich einige Stunden Vergleiche und hilft Ihnen, eine fundiertere Entscheidung bei der Gestaltung Ihrer Programme zu treffen.