原子について語るには、原子とは何か、原子の操作とは何かを考える必要があります。原子とは、その名が示すように、最小の不可分粒子です。ここでは、クォーク粒子を無視して原子という言葉を象徴することができます。原子操作とは、1つまたは一連の不可分でブロック化された操作のことです。
アトムとは「それ以上分割できない最小の粒子」、アトミック・オペレーションとは「中断できない操作または一連の操作」という意味です。
原子は何をしたのですか?
セッターメソッド
static inline void reallySetProperty(id self, SEL _cmd, id newValue, ptrdiff_t offset, bool atomic, bool copy, bool mutableCopy)
{
...
if (!atomic) {
oldValue = *slot;
*slot = newValue;
} else {
spinlock_t& slotlock = PropertyLocks[slot];
slotlock.lock();
oldValue = *slot;
*slot = newValue;
slotlock.unlock();
}
objc_release(oldValue);
}
ゲッターメソッド
id objc_getProperty(id self, SEL _cmd, ptrdiff_t offset, BOOL atomic) {
...
// Retain release world
id *slot = (id*) ((char*)self + offset);
if (!atomic) return *slot;
// Atomic retain release world
spinlock_t& slotlock = PropertyLocks[slot];
slotlock.lock();
id value = objc_retain(*slot);
slotlock.unlock();
// for performance, we (safely) issue the autorelease OUTSIDE of the spinlock.
return objc_autoreleaseReturnValue(value);
}
ソースコードからわかるように、アトミック設定後、セッターメソッドとゲッターメソッドは読み書き時にロックされ、操作完了後にロックが解除されます。これにより、読み書きデータの整合性が保証されます。
atomicはスレッドの安全性を保証しますか?
公式文書には、アトミティシティはオブジェクトのスレッドセーフティとは異なるという明確なヒントがあります。
Note: Property atomicity is not synonymous with an object s thread safety.
ドキュメントには簡単な例が示されています。あるスレッドで、ある人の姓と名が変わっています。同時に別のスレッドからその人の名前にアクセスしたいとします。図を見てわかるように、姓が変更されていないときに姓にアクセスし、 姓が変更されたときに名にアクセスすると、ミスマッチが発生する可能性があります。実際、その人の名前はZhangsanからLisanに変更されただけで、別のスレッドが最初の名前Zhangsanを取得するかもしれません。
これは最も単純な例です。実際には、例えばプロパティが変数配列である場合なども考えることができます。ご覧のように、アトミックではセッターとゲッターのメソッドにロックを追加するだけで、データの読み取りと書き込みの整合性を保証することができます。
なぜ非原子なのですか?
iOSの開発では、オブジェクトのスレッドセーフティがより重視され、プロパティ自体のデータのアトミック性の影響はむしろそれほど大きくありません。アトミックに設定しているため、setやgetの際にロックやアンロック処理が発生し、パフォーマンスのオーバーヘッドが増加します。非アトミックに設定すると、これらの処理がなくなります。したがって、異なるスレッドでデータの正確さと一貫性を保証する必要がある場合は、atomicを使用してください。これは、セッターメソッドとゲッターメソッドによってこのデータ自体を読み書きする場合にのみ有効です。それ以外の場合は nonatomic に設定できます。
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