33

検索したところ、不変はスレッドセーフですが、可変はそうではありません。これで結構です。しかし、私は誤解を招くようなメモ、ブログ、スレッドセーフに関するアトミックと非アトミックに関する回答を受け取りました。親切に回答の説明をしてください。

「name」というアトミック文字列プロパティがあり、[self setName:@"A"]スレッドAから呼び出し[self setName:@"B"]、スレッドBから呼び出し[self name]、スレッドCから呼び出すと、異なるスレッドでのすべての操作がシリアルに実行されます。つまり、1つのスレッドがsetterまたはgetterの場合、他のスレッドが待機します。これにより、プロパティ「name」の読み取り/書き込みは安全になりますが、別のスレッドDが[name release]同時に呼び出すと、ここにsetter / getter呼び出しが含まれないため、この操作によってクラッシュが発生する可能性があります。つまり、オブジェクトは読み取り/書き込みセーフ(ATOMIC)ですが、別のスレッドが任意のタイプのメッセージをオブジェクトに同時に送信できるため、スレッドセーフではありません。

プロパティ「name」が非アトミックである場合、上記の例のすべてのスレッド(A、B、C、およびD)が同時に実行され、予測できない結果が生成されます。アトミックの場合、A、B、またはCのいずれかが最初に実行されますが、Dは引き続き並行して実行できます。

これについてのあなたのコメントは私たちを助けるでしょう....

そして、私の質問は、「ココア、アトミック、または非アトミックのどちらでスレッドセーフですか?」です。

4

7 に答える 7

69

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つの良い点は、必要な粒度がすべて揃っていることです。多くの場合、アトミックに使用されるスピンロックよりも重いですが、通常は取得が少なくて済むため、通常のロックを正しく使用すると非常に高速になります。 。

于 2012-09-10T08:48:13.093 に答える
14

アトミックは変数へのアトミックアクセスを保証しますが、コードスレッドを安全にするわけではありません。非原子的でもありません。

「アトミック」を使用すると、合成されたセッター/ゲッターメソッドは、他のスレッドでのセッターアクティビティに関係なく、常に値全体がゲッターから返されるか、セッターによって設定されるようにします。したがって、スレッドBがセッターを呼び出しているときにスレッドAがゲッターの途中にある場合、実際の実行可能な値がAの呼び出し元に返されます。非アトミックの場合、そのような保証はありません。

于 2012-09-10T07:44:44.197 に答える
9

アトミックは次のスレッドを安全にします。

self.myProperty = value;

また

id value = self.myProperty

次のスレッドは安全になりません

[myPorperty addObject:value];

Atomicを使用すると、プロパティを設定または取得するスレッドセーフになりますが、そのプロパティ自体のメソッドの呼び出しをスレッドセーフにすることはできません。

値の設定または取得には複数のCPU命令が必要になる可能性があるため、設定または取得は途中で中断される可能性があり、別のスレッドが何かを実行して、値の設定または取得で前のスレッドの進行を無効にすることができます。

アトミックは、1つの不可分な命令で発生したかのように値を設定または取得し、他のスレッドが途中でステップして物事を台無しにすることができないように設定または取得すると言います。

不変オブジェクトは変更できないため、スレッドセーフでシンプルです。そのため、ある不変オブジェクトから別のオブジェクトにプロパティを変更して、アトミックにしない限りパーツが安全にならないようにすることができます。

于 2012-09-10T11:38:17.243 に答える
2

ARCの前にスレッドセーフに必要だった、言及されていない「アトミック」の別のプロパティがあります(おそらくまだそうです)。最初にそれが必要な理由を説明します。たとえば、ARCを使用せずに、オブジェクトプロパティを読み取り、すぐに保持するとします。ただし、プロパティの読み取りとretain呼び出しの間に別のスレッドが入り、オブジェクトプロパティをnilに設定すると、オブジェクトの割り当てが解除される可能性があります。割り当てが解除されたオブジェクトに保持を送信しますが、これは不健康です。また、タイミングが適切な場合にのみ発生するため、非常にまれなバグになります。これを防ぐために、アトミックオブジェクトプロパティは常に自動解放されたオブジェクトを返します。

于 2014-02-24T10:12:04.000 に答える
0
  1. Atomicはスレッドセーフです。
  2. 別のタイプのセマフォであるMutex、スピン、または条件としてロックします。続きを読む... https://developer.apple.com/library/ios/documentation/Cocoa/Conceptual/Multithreading/ThreadSafety/ThreadSafety.html
于 2016-05-04T14:02:57.783 に答える
-1

アプリ内でデッドロックが発生しないように、ロックメカニズムの実装を検討する必要があります。また、Coreデータを実装している場合は、iOSスレッドセーフについて読む必要があります。

見る。

http://developer.apple.com/library/iOS/#documentation/Cocoa/Conceptual/Multithreading/ThreadSafetySummary/ThreadSafetySummary.html

http://developer.apple.com/library/iOS/#documentation/Cocoa/Conceptual/Multithreading/ThreadSafety/ThreadSafety.html%23//apple_ref/doc/uid/10000057i-CH8-SW1

于 2012-09-10T08:37:02.137 に答える
-8

非アトミックはスレッドセーフです。変数の値を取得することが保証されています。

于 2015-03-09T06:29:48.600 に答える