ios 原子属性と非原子属性の違いは何ですか?





13 Answers

これはAppleのdocumentationで説明されていますが、実際に何が起こっているかの例は次のとおりです。 「原子」キーワードがないことに注意してください。「非原子的」を指定しないとプロパティはアトミックですが、「アトミック」を明示的に指定するとエラーになります。

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

- (UITextField *) userName {
    return userName;
}

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

さて、原子の変形はもう少し複雑です:

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

基本的に、原子バージョンはスレッドの安全を保証するためにロックを取らなければならず、また、オブジェクトの参照カウントをバンプして(そして、それをバランスさせるための自動解放カウント)、オブジェクトが呼び出し側のために存在することが保証されます別のスレッドが値を設定している場合に、潜在的な競合状態になり、refカウントが0に低下します。

実際には、プロパティーがスカラー値かオブジェクトかどうか、保持、コピー、読み取り専用、非原子質などがどのように相互作用するかによって、これらの処理がどのように動作するかについては数多くのバリエーションがあります。 一般に、プロパティシンセサイザーは、すべての組み合わせに対して「正しいこと」を実行する方法を知っています。

ios objective-c properties atomic nonatomic

プロパティの宣言では、 atomicnonatomic平均は何ですか?

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

これらの3つの運用上の違いは何ですか?




違いを理解する最も良い方法は、次の例を使用することです。

"name"というアトミックな文字列プロパティがあり、スレッドAから[self setName:@"A"]を呼び出す場合はスレッドBから[self setName:@"B"]を呼び出し、 [self name]をスレッドCの場合、異なるスレッドのすべての操作は順次実行されます。つまり、あるスレッドがセッターまたはゲッターを実行している場合、他のスレッドは待機します。

これにより、プロパティ "name"の読み書きは安全になりますが、別のスレッドDが[name release]同時に呼び出すと、ここに関わるセッター/ゲッターコールがないため、この操作でクラッシュする可能性があります。 これは、オブジェクトが読み書き可能(ATOMIC)であることを意味しますが、別のスレッドが同時にオブジェクトにメッセージを送信できるため、スレッドセーフではありません。 開発者は、そのようなオブジェクトに対するスレッドの安全性を保証する必要があります。

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




アトミック =スレッドの安全性

非アトミック =スレッドの安全性なし

スレッドの安全性:

インスタンス変数は、ランタイム環境によるそれらのスレッドの実行のスケジューリングまたはインターリーブに関係なく、呼び出しコードの部分での追加の同期やその他の調整なしに、複数のスレッドからアクセスされたときに正しく動作する場合、スレッドセーフです。

我々の文脈では:

スレッドがインスタンスの値を変更すると、変更された値がすべてのスレッドで使用可能になり、一度に1つのスレッドだけが値を変更できます。

atomicを使う場所:

インスタンス変数がマルチスレッド環境でアクセスされる場合

atomic含意:

nonatomicものはランタイムからのウォッチドッグ作業を必要としないため、 nonatomicほど高速ではありません。

nonatomicを使用するnonatomic

インスタンス変数が複数のスレッドによって変更されない場合は、それを使用できます。 パフォーマンスが向上します。




非常に多くの記事を読んだら、の投稿とデモアプリケーションを使って変数の属性の属性を確認した後、私はすべての属性の情報をまとめました。

  1. atomic //デフォルト
  2. nonatomic
  3. strong = retain //デフォルト
  4. weak = unsafe_unretained
  5. retain
  6. assign //デフォルト
  7. unsafe_unretained
  8. copy
  9. readonly
  10. readwrite //デフォルト

iOSのVariableプロパティの属性または修飾子の記事では、上記のすべての属性を見つけることができます。これは間違いなくあなたを助けます。

  1. atomic

    • atomicは、変数(静的型)にアクセスするスレッドが1つだけであることを意味します。
    • atomicはスレッドセーフです。
    • しかし、それはパフォーマンスが遅いです
    • atomicはデフォルトの動作です
    • ガーベジコレクションされていない環境(つまり、retain / release / autoreleaseを使用している場合)のアトミックアクセサは、別のスレッドが値の正しい設定/取得を妨げないようにロックを使用します。
    • 実際にはキーワードではありません。

    例:

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

    • nonatomicは、複数のスレッドが変数(動的型)にアクセスすることを意味します。
    • nonatomicはスレッドnonatomicはありません。
    • しかし、それはパフォーマンスが速い
    • nonatomicはデフォルト動作ではありません。 nonatomicキーワードをproperty属性に追加する必要があります。
    • 2つの異なるプロセス(スレッド)が同じ変数に同時にアクセスすると、予期しない動作が発生する可能性があります。

    例:

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



原子:

Atomicは、プロパティへのアクセスがアトミックな方法で実行されることを保証します。 例えば、完全に初期化されたオブジェクトを常に返します。あるスレッドのプロパティの取得/設定は、別のスレッドがアクセスする前に完了する必要があります。

すぐに2つのスレッドで次の関数が発生すると想像すれば、なぜ結果が綺麗でないのかを知ることができます。

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

  ...
}

長所:完全に初期化されたオブジェクトが返されるたびに、マルチスレッドの場合に最良の選択となります。

短所:パフォーマンスが低下し、実行が少し遅くなる

非原子性:

Atomicとは異なり、完全に初期化されたオブジェクトが毎回返されることは保証されません。

長所:非常に速い実行。

短所:マルチスレッドの場合のゴミ値の可能性。




Atomicはスレッドセーフであり速度遅く 、同一ゾーン上で何スレッドがアクセスしようとしても、ロックされた値だけが保証されます(保証されているわけではありません) 。 アトミックを使用する場合、この関数の内部に記述されたコードはクリティカルセクションの一部になり、一度に1つのスレッドしか実行できません。

スレッドの安全性だけを保証します。 それはそれを保証するものではありません。 私が意味することは、あなたがあなたの車のための専門家の運転手を雇うことです、それでも、車が事故に会わないことを保証するものではありません。 しかし、確率はわずかです。

原子的 - それは分解できないので、結果は期待される。 非原子的 - 他のスレッドがメモリゾーンにアクセスすると、それを修正することができるので、予期しない結果になります。

コードトーク:

アトミックgetterとプロパティスレッドセーフのセッターを作る。 例えば、あなたが書いたものなら、

self.myProperty = value;

スレッドセーフです。

[myArray addObject:@"Abc"] 

スレッドセーフではありません。




デフォルトatomic です。つまり、プロパティを使用するたびにパフォーマンスが低下しますが、スレッドセーフです。 Objective-Cはロックを設定しているので、setter / getterが実行されている限り、実際のスレッドだけが変数にアクセスできます。

ivarを持つプロパティのMRCの例_internal:

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

したがって、これらの最後の2つは同じです:

@property(atomic, retain) UITextField *userName;

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

一方、 nonatomicはコードに何も追加しません。 したがって、あなた自身がセキュリティ機構をコード化すればスレッドセーフです。

@property(nonatomic, retain) UITextField *userName;

キーワードを最初のプロパティ属性として書き込む必要はありません。

これは、プロパティ全体がスレッドセーフであることを意味するわけではありません。 setter / getterのメソッド呼び出しのみです。 しかし、あなたがセッターを使用し、その後2つの異なるスレッドで同時にゲッターをすると、それも壊れる可能性があります!




@propertyの属性について議論する前に、@propertyの使い方を知っておく必要があります。 @propertyは、クラスがカプセル化しようとしている情報を定義する方法を提供します。 @propertyを使用してオブジェクト/変数を宣言すると、そのオブジェクト/変数はそのクラスをインポートする他のクラスからアクセス可能になります。 ヘッダーファイルで@propertyを使用してオブジェクトを宣言する場合、実装ファイルで@synthesizeを使用してオブジェクトを合成する必要があります。

例:

.hクラス

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

.mクラス

@implementation ExampleClass
   @synthesize name;
@end

コンパイラはnameのアクセサメソッドを合成します。

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

@propertyのアトリビュートのリスト:アトミック 非原子。 保持する。 コピー。 読み取り専用。 読み書き。 割り当てます。 強い。

原子:これはデフォルトの動作です。 オブジェクトがアトミックとして宣言されている場合、スレッドセーフになります。 スレッドセーフとは、一度にそのクラスの特定のインスタンスの1つのスレッドだけがそのオブジェクトに対する制御を持つことができることを意味します。

例:

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

nonatomic:スレッドセーフではありません。 nonatomicプロパティ属性を使用すると、合成されたアクセサが値を直接設定または返すだけで、同じ値が別のスレッドから同時にアクセスされた場合に何が起こるかは保証されません。 このため、原子以外のプロパティにアクセスする方が高速です。 @property (nonatomic)NSString *name;

retain:属性がオブジェクトへのポインタである場合に必要です。セッターメソッドはオブジェクトの保持カウントを増加させ、オートリリースプールでメモリを占有します。 @property (retain)NSString *name;

copy:copyを使うと、retainを使うことはできません。 クラスのコピーインスタンスを使用すると、独自のコピーが含まれます。 変更可能な文字列が設定され、その後変更されたとしても、インスタンスは設定された時点の値を取得します。 セッターメソッドとゲッターメソッドは合成されません。

@property (copy) NSString *name;

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

readonly:setterメソッドを使用してプロパティを変更することを許可しない場合は、プロパティを読み取り専用に宣言できます。 @property (readonly) NSString *name;

readwrite:はデフォルトの動作です。 readwrite属性を明示的に指定する必要はありません。

@property (readwrite) NSString *name;

assign:それをコピーまたは保持するのではなく、インスタンス変数に直接代入するセッターを生成します。これは、NSIntegerやCGFloatのようなプリミティブ型や、代理人のように直接所有していないオブジェクトに最適です。

@property (assign) NSInteger year;

強い:保持の代わりです。 @property (nonatomic, strong) AVPlayer *player;

unsafe_unretained:弱い参照をサポートしていないCocoaとCocoa Touchにはいくつかのクラスがあります。弱いプロパティや弱いローカル変数を追跡してそれらを追跡することはできません。これらのクラスにはNSTextView、NSFont、NSColorSpaceなどがあります。これらのクラスの1つに弱い参照を使用する必要がある場合は、安全でない参照を使用する必要があります。安全でない参照は弱い参照と似ていますが、それは関連オブジェクトを有効に保ちませんが、宛先オブジェクトが割り当て解除されるとnilに設定されません。

@property (unsafe_unretained) NSObject *unsafeProperty;




  • -Atomicは、変数(静的型)にアクセスするスレッドが1つだけであることを意味します。
  • -Atomicはスレッドセーフです。
  • しかし、パフォーマンスは遅いです

宣言する方法:

原子はデフォルトであるので、

@property (retain) NSString *name;

ANDと実装ファイル

self.name = @"sourov";

3つのプロパティに関連するタスクが

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

すべてのプロパティは並行して動作します(非同期など)。

スレッドAから "name"を呼び出すと、

そして

あなたが電話すると同時に

[self setName:@"Datta"]

スレッドBから、

今、もし* nameプロパティは非アトミックですその後、

  • Aの値 "Datta"を返します
  • Bの値 "Datta"を返します

なぜ非原子はスレッドセーフではないと言われるのですか?しかし、並列実行のためにパフォーマンスが速いです

今すぐ* nameプロパティがアトミックな場合

  • それはAの値 "Sourov"を保証します
  • 次に、Bの値 "Datta"を返します

それがアトミックがスレッドセーフ呼ばれる理由です。そのため、読み取り/書き込みセーフと呼ばれています

このような状況操作は連続的に実行されます。パフォーマンスが遅い

- Nonatomicは、複数スレッドが変数(動的型)にアクセスすることを意味します。

- 非原子的なスレッドは安全ではありません。

- しかし、パフォーマンスは速いです

非原子はデフォルトの振る舞いではなく、我々はプロパティ属性に非原子キーワードを追加する必要があります。

In SwiftについてObjCの意味でSwiftプロパティが非原子的であることを確認します。1つの理由は、プロパティごとのアトミシティがあなたのニーズに十分かどうかを考えているからです。

リファレンス:https://forums.developer.apple.com/thread/25642 : https://forums.developer.apple.com/thread/25642

より多くの情報はウェブサイトhttp://rdcworld-iphone.blogspot.in/2012/12/variable-property-attributes-or.htmlをご覧ください




atomicプロパティは、getterおよびsetterを行っているスレッドの数に関係なく、完全に初期化された値を保持します。

nonatomicプロパティは、合成されたアクセサが単に値を直接設定または返すことを指定します。同じ値が別のスレッドから同時にアクセスされた場合に何が起こるかは保証されません。




アトミックを使用している場合は、スレッドが安全で読み取り専用であることを意味します。nonatomicを使用している場合は、複数のスレッドが変数にアクセスし、スレッドが安全ではないことを意味しますが、高速で実行され、読み書き操作が実行されます。これは動的なタイプです。




全体の混乱を単純化するために私たちはmutexロックを理解してみましょう。ミューテックスロックは、オブジェクトの変更可能性をロックします。オブジェクトがクラスによってアクセスされている場合、他のクラスは同じオブジェクトにアクセスすることはできません。 lock.NowはFIFOモードで機能し、同じインスタンスを共有する2つのクラスによって影響されないフローを保証します。タスクがメインスレッド上にある場合、UIを保持しパフォーマンスを低下させる可能性があるため、




アトミックプロパティアトミックプロパティで割り当てられた変数がスレッドアクセスを1つしか持たず、スレッドセーフでパフォーマンス面で優れている場合は、デフォルトの動作になります。

非アトミックプロパティアトミックプロパティで割り当てられた変数で、マルチスレッドアクセスを持ち、スレッドセーフではなく、パフォーマンスパースペクティブでは遅くなるというデフォルトの動作を持ち、2つの異なるスレッドが同時に変数にアクセスしたい場合予期しない結果をもたらすでしょう。




Related