ObjCプロパティの場合-どちらもスレッドセーフではありません。
Atomicは、スレッドエラーに対してより耐性があります。全体として、これは奇妙なデフォルトです。アトミックを好むシナリオはごくわずかです。アトミックは正しさの可能性を高めることができますが、レベルが低すぎるため、適切なロックメカニズムの代わりと見なされます。したがって、スレッドセーフが必要な場合でも、アトミック読み取り/書き込みに加えて、他の同期プリミティブが必要です。スレッドセーフが必要ない場合(たとえば、インスタンスが不変であるか、メインスレッドからのみ実行されることを意図している場合)、atomicは何も追加しません。
スレッドエラーに耐性があることは「品質」ではありません。実際のスレッドエラーをマスクし、再現と検出をより困難にするのに役立ちます。
また、可変型と不変型は実際にはスレッドセーフを保証しないことに注意してください。'Mutable'は、インターフェイスのみを参照するためにObjC名で使用される場合があります。不変インスタンスの内部は、実際には内部可変状態を持っている場合があります。つまり、可変サブクラスを持つ型がスレッドセーフであるとは限りません。
質問の拡大:
「name」というアトミック文字列プロパティがあり、スレッドAから[self setName:@ "A"]を呼び出す場合は、スレッドBから[self setName:@ "B"]を呼び出し、スレッドCの場合、異なるスレッドでのすべての操作はシリアルに実行されます。つまり、1つのスレッドがsetterまたはgetterを実行している場合、他のスレッドは待機します。
すべてのスレッドが同時にプロパティの読み取りや書き込みを試みた場合、一度に1つのスレッドのみがアクセスでき、プロパティがアトミックである場合、他のスレッドはブロックされます。プロパティが非アトミックである場合、それらはすべて、同時に変数への保護されていない読み取りおよび書き込みアクセス権を持ちます。
別のスレッドDが[namerelease]を同時に呼び出す場合、ここにはsetter / getter呼び出しが含まれていないため、この操作によってクラッシュが発生する可能性があります。
正しい。
つまり、オブジェクトは読み取り/書き込みセーフ(ATOMIC)ですが、別のスレッドが任意のタイプのメッセージをオブジェクトに同時に送信できるため、スレッドセーフではありません。
まあ、それには本当にたくさんあります。一般的な例は次のとおりです。
@interface MONPerson : NSObject
@property (copy) NSString * firstName;
@property (copy) NSString * lastName;
- (NSString *)fullName;
@end
アトミックまたは非アトミックでは、あるスレッドがそのインスタンスから読み取り、別のスレッドがそのインスタンスに書き込みを行う場合、同期メカニズム(ロックなど)が必要になります。1つのMONPersonのfirstNameと別のlastNameになってしまう可能性があります-ゲッターの戻り値が返される前にオブジェクトが変更されている可能性があります。そうでない場合は、次のようになります。
スレッドA:
p.firstName = @"Rob";
スレッドB:
p.firstName = @"Robert";
スレッドA:
label.string = p.firstName; // << uh, oh -- will be Robert
プロパティ「name」が非アトミックである場合、上記の例のすべてのスレッド(A、B、C、およびD)が同時に実行され、予測できない結果が生成されます。
右-初期症状は、参照カウントの不均衡(リーク、過剰放出)である可能性があります。
アトミックの場合、A、B、またはCのいずれかが最初に実行されますが、Dは引き続き並行して実行できます。これについてコメントしてください。
正しい。しかし、上記の例を見ると、アトミックだけがロックの適切な代替となることはめったにありません。代わりに次のようにする必要があります。
スレッドA:
[p lock]; // << wait for it… … … …
// Thread B now cannot access p
p.firstName = @"Rob";
NSString fullName = p.fullName;
[p unlock];
// Thread B can now access p
label.string = fullName;
スレッドB:
[p lock]; // << wait for it… … … …
// Thread A now cannot access p
…
[p unlock];
アトミックアクセサーは、非アトミックアクセスよりも平均して20倍以上遅くなる可能性があります。同様に、クラスがスレッドセーフである必要があり、可変状態である場合、並行シナリオで動作するときにロックを使用することになります。適切なロックにより、必要なすべての保証が提供されます。このシナリオでは、アトミックアクセサーは冗長であり、アトミックを使用するとCPU時間のみが追加されます。通常のロックのもう1つの良い点は、必要な粒度がすべて揃っていることです。多くの場合、アトミックに使用されるスピンロックよりも重いですが、通常は取得が少なくて済むため、通常のロックを正しく使用すると非常に高速になります。 。