非アトミックとアトミックのiOS開発の違い



Ios Development Difference Between Nonatomic



デフォルトでは、コンパイラによって合成されたメソッドは、ロックメカニズムを通じてアトミック性を保証します。属性に非アトミック特性がある場合、同期ロックは必要ありません。

2つのスレッドが同時に属性を読み取る場合、いつでも有効な属性値を確認できます。



ロックしない(または非アトミックセマンティクスを使用する)と、スレッドの1つがプロパティ値を書き換えているときに、別のスレッドが突然侵入して、変更されていないプロパティ値を読み取る可能性があります。状況が確認されると、スレッドによって読み取られた属性の値が間違っている可能性があります。

iOSで同期ロックを使用するとコストがかかるため、パフォーマンスの問題が発生する可能性があります。一般に、属性は「アトミック」であってはなりません。これは「スレッドセーフ」を保証するものではないためです。 「スレッドセーフ」操作を実現するには、ウェイクアップするためにより深いロックメカニズムが必要です。



たとえば、スレッドがプロパティ値を連続して複数回読み取っているときに値を繰り返し書き換えると、プロパティがアトミックとして宣言されていても、異なるプロパティ値が読み取られます。

したがって、iOSプログラムは通常、非アトミック属性を使用します。ただし、Mac OS Xプログラムでは、通常、アトミック属性を使用するときにパフォーマンスのボトルネックはありません。

誰かがコメントにコメントしたので、質問を追加してください。アトミックはスレッドセーフでなければなりません。答えはNOです。



非アトミックメモリ管理セマンティクスは非アトミックです。非アトミック操作は本質的にスレッドセーフではありませんが、アトミック操作はアトミックですが、スレッドセーフであることを意味するわけではありません。それは正しい可能性を高め、スレッドエラーを回避するためにより良い可能性がありますが、それでも安全ではありません。

アトミックと非アトミックの本質的な違いは、実際にはセッターメソッドの操作の違いであると言うために:

非アトミックの実装:
'' '

  • (void)setCurrentImage:(UIImage *)currentImage
    {{
    if(_currentImage!= currentImage){
    [_currentImageリリース]
    _currentImage = [currentImage保持]

    // do something

    }
    }

  • (UIImage *)currentImage
    {{
    _currentImageを返します
    }
    '' '
    アトミック実装:
    '' '

  • (void)setCurrentImage:(UIImage *)currentImage
    {{
    @synchronized(self){
    if(_currentImage!= currentImage){
    [_currentImageリリース]
    _currentImage = [currentImage保持]

    // do something }

    }
    }

  • (UIImage *)currentImage
    {{
    @synchronized(self){
    _currentImageを返します
    }
    }
    '' '
    @synchronizedディレクティブの使用
    @synchronizedディレクティブは、Objective-Cコードでその場でミューテックスロックを作成するための便利な方法です。 @synchronizedディレクティブは、他のミューテックスロックと同じように機能します。つまり、異なるスレッドが同じロックを同時に取得するのを防ぎます。ただし、この場合、ミューテックスまたはロックオブジェクトを直接作成する必要はありません。代わりに、次の例に示すように、Objective-Cオブジェクトをロックトークンとして使用するだけです。
    '' '

  • (void)myMethod:(id)anObj
    {{
    @synchronized(anObj)
    {{
    //中括弧の間はすべて@synchronizedディレクティブで保護されています。
    }
    }
    '' '
    @synchronizedディレクティブに渡されるオブジェクトは、保護されたブロックを区別するために使用される一意の識別子です。上記のメソッドを2つの異なるスレッドで実行し、各スレッドのanObjパラメーターに異なるオブジェクトを渡すと、それぞれがロックを取得し、他のスレッドによってブロックされることなく処理を続行します。ただし、両方の場合に同じオブジェクトを渡すと、一方のスレッドが最初にロックを取得し、もう一方のスレッドは最初のスレッドがクリティカルセクションを完了するまでブロックします。

予防措置として、@ synchronizedブロックは保護されたコードに例外ハンドラーを暗黙的に追加します。このハンドラーは、例外がスローされた場合にミューテックスを自動的に解放します。つまり、@ synchronizedディレクティブを使用するには、コードでObjective-C例外処理も有効にする必要があります。暗黙の例外ハンドラーによって引き起こされる追加のオーバーヘッドが必要ない場合は、ロッククラスの使用を検討する必要があります。

@synchronizedディレクティブの詳細については、「Objective-Cプログラミング言語」を参照してください。

アトミックを使用すると、属性の読み取りと書き込みはアトミックですが、スレッドエラーが発生する可能性があります。スレッドAが書き込み操作を実行すると、他のスレッドの読み取りまたは書き込み操作が操作を待機します。 Aスレッドの書き込み操作が終了すると、Bスレッドが書き込みを行い、異なるスレッドに対するすべての操作が順番に実行されます。つまり、1つのスレッドがゲッター/セッターを実行している場合、他のスレッドは待機する必要があります。スレッドCがAスレッドの読み取り操作の前に属性を解放すると、プログラムもクラッシュします。したがって、アトミックを使用するだけではスレッドは安全になりません。また、スレッドの安全性を確保するために、スレッドにロックを追加する必要があります。

より正確には、読み取りと書き込みのセキュリティが必要ですが、他のスレッドが読み取りと書き込み以外の操作を実行できるため、スレッドセーフではありません。スレッドセーフは、開発者がそれを保証することを要求します。

実際、アトミックを使用してNSMutableArrayを操作するなど、ゲッターとセッターがアトミックであるかどうかに関係なく、スレッドがデータの読み取りにループし、スレッドがデータの書き込みにループすると、間違いなくメモリの問題が発生します。これはゲッターとセッターズウッドには関係があります。

私は最近、Doubanでこの記事が気分が良いのを見ました、これはリンクです: https://www.douban.com/note/486901956/

転載:https://www.jianshu.com/p/ae1efeb3480a