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


12 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に低下します。

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

Question

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

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

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




Before discussing about the attributes of @property, you should know what is the use of @property. @property offers a way to define the information that a class is intended to encapsulate. If you declare an object/variable using @property, then that object/variable will be accessible to other classes importing its class. If you declare an object using @property in the header file, then you have to synthesize it using @synthesize in the implementation file.

例:

.h class

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

.m class

@implementation ExampleClass
   @synthesize name;
@end

Now the compiler will synthesize accessor methods for name.

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

List of attributes of @property : atomic. nonatomic. retain. copy. readonly. readwrite. assign. strong.

atomic : It is the default behaviour. If an object is declared as atomic then it becomes thread-safe. Thread-safe means, at a time only one thread of a particular instance of that class can have the control over that object.

例:

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

nonatomic: It is not thread-safe. You can use the nonatomic property attribute to specify that synthesized accessors simply set or return a value directly, with no guarantees about what happens if that same value is accessed simultaneously from different threads. For this reason, it's faster to access a nonatomic property than an atomic one. @property (nonatomic)NSString *name;

retain: is required when the attribute is a pointer to an object.The setter method will increase retain count of the object, so that it will occupy memory in autorelease pool. @property (retain)NSString *name;

copy: If you use copy, you can't use retain. Using copy instance of the class will contain its own copy. Even if a mutable string is set and subsequently changed, the instance captures whatever value it has at the time it is set. No setter and getter methods will be synthesized.

@property (copy) NSString *name;

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

readonly: If you don't want to allow the property to be changed via setter method, you can declare the property readonly. @property (readonly) NSString *name;

readwrite: is the default behaviour. You don't need to specify readwrite attribute explicitly.

@property (readwrite) NSString *name;

assign: will generate a setter which assigns the value to the instance variable directly, rather than copying or retaining it. This is best for primitive types like NSInteger and CGFloat, or objects you don't directly own, such as delegates.

@property (assign) NSInteger year;

strong: is a replacement for retain. @property (nonatomic, strong) AVPlayer *player;

unsafe_unretained: There are a few classes in Cocoa and Cocoa Touch that don't yet support weak references, which means you can't declare a weak property or weak local variable to keep track of them. These classes include NSTextView, NSFont and NSColorSpace,etc. If you need to use a weak reference to one of these classes, you must use an unsafe reference. An unsafe reference is similar to a weak reference in that it doesn't keep its related object alive, but it won't be set to nil if the destination object is deallocated.

@property (unsafe_unretained) NSObject *unsafeProperty;




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

"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は引き続き並行して実行できます。




マルチスレッドコードでプロパティを使用している場合は、非アトミックアトミックとアトミックアトリビュートの違いを見ることができます。 非原子は原子よりも速く、原子はスレッドセーフであり、非原子ではありません。

Vijayendra Tripathiは既にマルチスレッド環境の例を挙げています。




To simplify the entire confusion let us understand mutex lock.Mutex lock as per the name locks the mutability of the object.So if the object is accessed by a class no other class can access the same object.In iOS @sychronise also provide the mutex lock.Now it serve in FIFO mode and ensures the flow is not affected by two classes sharing the same instance.However if the task is on main thread avoid accessing object using atomic properties as it may hold your UI and degrade the performance




The atomic property ensures to retain a fully initialised value irrespective of how many threads are doing getter & setter on it.

The nonatomic property specifies that synthesized accessors simply set or return a value directly, with no guarantees about what happens if that same value is accessed simultaneously from different threads.




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

  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;
    



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

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

スレッドの安全性:

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

我々の文脈では:

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

atomicを使う場所:

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

atomic含意:

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

nonatomicを使用するnonatomic

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




原子:

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とは異なり、完全に初期化されたオブジェクトが毎回返されることは保証されません。

長所:非常に速い実行。

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




Let's take an example:-

@property (atomic, strong) NSString *atomicProperty;
@property (nonatomic, strong) NSString *nonAtomicProperty;

Atomic Properties:-

1) Defining a property as atomic will guarantee that a valid value will be returned. Notice that valid does not always mean correct (more on that in the next section of this post)

2) Atomic properties suffer from the minor performance hit due to locking and unlocking before and after setting/getting a value.

3) Atomic is the default behavior for properties — this is what you get if you don't specify anything.

Non-Atomic Properties:-

1) Nonatomic properties have no guarantee regarding the returned value.

2) It can be the correct value, a partially written value or even some garbage value.

3) As most things that are not safe — this comes with an enhanced speed of accessing these properties.

Objective-Cランタイムはこれをプログラムでどのように行うのかを見てみましょう。

Objective-Cランタイムの "set value"メソッドを見てみましょう。

アトミックプロパティがロックを使用してセット操作を保護している間に、非アトミックなプロパティがプロパティの値を直接設定していることに注目してください




If you are using atomic, it means the thread will be safe and read-only. If you are using nonatomic, it means the multiple threads access the variable and is thread unsafe, but it is executed fast, done a read and write operations; this is a dynamic type.




デフォルト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つの異なるスレッドで同時にゲッターをすると、それも壊れる可能性があります!




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

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

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

コードトーク:

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

self.myProperty = value;

スレッドセーフです。

[myArray addObject:@"Abc"] 

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




Related