2

strongオブジェクトへの参照を保持するオブジェクトがあります。

@property (nonatomic, strong) NSObject *thing;

他の場所には、オブジェクト参照を渡すメソッドがあります。

[thirdObject doSomething:secondObject.thing];

あるケース (100 万または 10 億のうち) では、オブジェクトがスワップされ、所有者がいないため、thirdObject がダングリング ポインターで動作することになりました。

これを行うことでこれを回避できますか?これは ARC の場合とは異なりますか?

NSObject *thing = secondObject.thing
[thirdObject doSomething:secondObject.thing];

そうでない場合、どうすればこれを回避できますか?

編集:メッセージは「割り当て解除されたインスタンス0xwhateverに送信されたメッセージ」です

4

1 に答える 1

7

ある種のスレッドセーフを適用しないと、複数のスレッドでプロパティを読み書きすることはできません。原則として、文字列のような単純なオブジェクトの場合は、適用atomicするだけで十分です。アトミック属性と非アトミック属性の違いを参照してください。それが何をするかの詳細については。

率直に言って、私はあまり好きではありませんatomic。私はそれが何をするかを知っていますが、本当に欲しいものを手に入れるには面倒な方法のようです (そしてしばしばあなたが望むものよりも少なくなってしまいます)。そして、それは非常に一般的な解決策ではありません。atomicアクセサーを「少し」カスタマイズすることはできません(aなどを追加するsetNeedsDisplayなど)。

そのため、私はキューベースのアクセサーが好きです。少し手間がかかりますが、多くの問題に効果的です。

@property (nonatomic, readwrite, strong) dispatch_queue_t thingQueue;
@property (nonatomic, strong) NSObject *thing;

- (id)init {
  ...
    _thingQueue = dispatch_queue_create("...", DISPATCH_QUEUE_CONCURRENT);
  ...
}

- (NSObject *)thing {
  __block NSObject *thing;
  dispatch_sync(self.thingQueue, ^{
    thing = _thing;
  });
  return thing;
}

- (void)setThing:(NSObject *)thing {
  dispatch_barrier_async(self.thingQueue, ^{
    _thing = thing;
  });
}

このシステムで私が気に入っているのは、すべてのリーダーを必要に応じて並行して実行できることです。ライタが更新を行おうとすると、何人のリーダが関係していても、枯渇しないことが保証されます。そして、それはいつもすぐに戻ります。また、値が変更されるキューには明確なポイントがあり、ライターの前に値を要求したリーダーは常に古い値を取得し、ライターの後のリーダーは常に新しい値を取得します。待ち行列に。

重要なのは、ゲッターが同期的であるため、値を取得できるまで待機し、セッターにバリアが含まれていることです。バリアとは、「実行中は、このキューから他のブロックをスケジュールできない」ことを意味します。したがって、多数のリーダー ブロックが並行して実行されていると、セッター バリアが現れて、すべてのリーダーが終了するのを待ちます。次に、値を設定して単独で実行し、その背後にあるリーダーを再び並行して実行できます。

于 2013-04-10T21:41:22.833 に答える