ios يكتب ما الفرق بين السمات الذرية وغير الذرية؟




معنى كلمة عنوان بالانجليزي (21)

ماذا يعني atomic وغير nonatomic في إعلانات الملكية؟

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

ما هو الفرق التشغيلي بين هؤلاء الثلاثة؟


ذرية (افتراضي)

Atomic هو الإعداد الافتراضي: إذا لم تقم بكتابة أي شيء ، فإن الخاصية الخاصة بك هي ذرية. يتم ضمان خاصية ذرية أنك إذا حاولت القراءة منها ، فسوف تحصل على قيمة صالحة. لا تقدم أي ضمانات حول قيمة هذه القيمة ، ولكن ستحصل على بيانات جيدة ، وليس مجرد ذاكرة عشوائية. ما يسمح لك القيام به هو إذا كان لديك عدة سلاسل عمليات أو عمليات متعددة تشير إلى متغير واحد ، يمكن قراءة مؤشر ترابط واحد ويمكن لمؤشر ترابط آخر الكتابة. في حالة ضررها في نفس الوقت ، يضمن مؤشر ترابط القارئ الحصول على واحدة من القيمتين: إما قبل التغيير أو بعد التغيير. ما لا تقدمه لك ذرية هو أي نوع من الضمانات حول أي من تلك القيم التي قد تحصل عليها. حقا الذري هو الخلط عادة مع كونها آمنة الصفحات ، وهذا غير صحيح. تحتاج إلى ضمان سلامة الصفحات الخاصة بك طرق أخرى. ومع ذلك ، ستضمن الذري أنك إذا حاولت القراءة ، فأنت تستعيد نوعًا من القيمة.

nonatomic

على الجانب الآخر ، غير ذري ، كما يمكن أن تخمن ، يعني فقط ، "لا تفعل ذلك الأشياء الذرية." ما تخسره هو أن تضمن أنك دائما تعود إلى شيء ما. إذا حاولت القراءة في منتصف الكتابة ، يمكنك استعادة بيانات البيانات المهملة. ولكن ، من ناحية أخرى ، تذهب أسرع قليلا. لأن الخصائص الذرية يجب أن تفعل بعض السحر لضمان أنك سوف تحصل على قيمة ، فهي أبطأ قليلا. إذا كانت خاصية يمكنك الوصول إليها كثيرًا ، فقد تحتاج إلى الانتقال إلى nonatomic للتأكد من أنك لا تتكبد هذه العقوبة بالسرعة.

انظر المزيد هنا: https://realm.io/news/tmi-objective-c-property-attributes/


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


إذا كنت تستخدم موقعك في تعليمة برمجية متعددة الخيوط ، فستتمكن من رؤية الفرق بين السمات الذرية وغير الذرية. غير الذرية هو أسرع من الذرية وذرية الخيط ، وليس غير مادية.

وقد أعطت Vijayendra Tripathi بالفعل مثالا لبيئة متعددة الخيوط.


الذري = السلامة موضوع

غير ذرية = لا يوجد سلامة مؤشر ترابط

سلامة الموضوع:

تكون متغيرات المثيل سلسلة آمنة إذا كانت تتصرف بشكل صحيح عند الوصول إليها من سلاسل عمليات متعددة ، بغض النظر عن جدولة أو تشذير تنفيذ مؤشرات الترابط هذه بواسطة بيئة التشغيل ، وبدون مزامنة إضافية أو تنسيق آخر من جانب شفرة الاتصال.

في سياقنا:

إذا كان مؤشر الترابط يغير قيمة المثيل ، فإن القيمة المتغيرة تكون متاحة لجميع سلاسل الرسائل ، ويمكن لمؤشر ترابط واحد فقط تغيير القيمة في كل مرة.

أين تستخدم atomic :

إذا كان سيتم الوصول إلى متغير المثيل في بيئة متعددة مؤشرات الترابط.

تداعيه atomic :

ليس بالسرعة غير nonatomic لأن nonatomic لا يتطلب أي عمل حراسة على ذلك من وقت التشغيل.

أين تستخدم غير nonatomic :

إذا كان متغير الحالة لن يتم تغييره بواسطة خيوط متعددة يمكنك استخدامه. يحسن الأداء.


تعني الذري أن خيطًا واحدًا فقط يصل إلى المتغير (نوع ثابت). الذري هو آمن الصفحات ، ولكنه بطيء.

يعني Nonatomic عدة مؤشرات ترابط الوصول إلى متغير (نوع الديناميكي). غير المادي غير آمن ، ولكنه سريع.


لقد وجدت شرحًا جيدًا للخصائص الذرية وغير الذرية here . إليك بعض النصوص ذات الصلة من نفس:

"ذرية" تعني أنه لا يمكن تقسيمها. في مصطلحات نظام التشغيل / البرمجة ، يعد استدعاء الدالة الذرية أمرًا لا يمكن قطعه - يجب تنفيذ الوظيفة بالكامل ، وعدم تبديلها من وحدة المعالجة المركزية عن طريق تبديل نظام التشغيل المعتاد حتى اكتمالها. فقط في حالة عدم معرفتك: نظرًا لأن وحدة المعالجة المركزية يمكنها القيام بشيء واحد فقط في كل مرة ، يقوم نظام التشغيل بتدوير الوصول إلى وحدة المعالجة المركزية لجميع العمليات الجارية في شرائح زمنية صغيرة ، لإعطاء وهم تعدد المهام. يمكن جدولة وحدة المعالجة المركزية (ويفعل) مقاطعة عملية في أي نقطة في تنفيذها - حتى في استدعاء منتصف وظيفة. لذا بالنسبة إلى إجراءات مثل تحديث متغيرات العداد المشتركة حيث يمكن أن تحاول عمليتان تحديث المتغير في نفس الوقت ، يجب أن يتم تنفيذهما "بشكل شاذ" ، أي يجب أن ينتهي كل إجراء تحديث بالكامل قبل أن يتم تبديل أي عملية أخرى إلى وحدة المعالجة المركزية.

لذا ، سأخمن أن الذري في هذه الحالة يعني أن أساليب القارئ لا يمكن أن تنقطع - في الواقع يعني أن المتغير (المتغيرات) التي تقرأها الطريقة لا يمكن أن يغير قيمتها في منتصف الطريق لأن بعض خيط / استدعاء / دالة أخرى تحصل على مبادلة على وحدة المعالجة المركزية.

ولأنه لا يمكن مقاطعة المتغيرات atomic ، فإن القيمة التي تحتوي عليها في أي نقطة هي (قفل الخيط) مضمونة لتكون غير فاسدة ، على الرغم من أن تأمين قفل الموضوع هذا يجعل الوصول إليها أبطأ. non-atomic المتغيرات non-atomic ، من ناحية أخرى ، فهي لا تقدم مثل هذه الضمانات ولكنها توفر ترف الوصول الأسرع. باختصار ، انتقل مع non-atomic عندما تعرف أن المتغيرات الخاصة بك لن يتم الوصول إليها من خلال عدة سلاسل في وقت واحد وتسريع الأمور.


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.



الافتراضي هو atomic ، وهذا يعني أنه يكلفك الأداء كلما كنت تستخدم الخاصية ، لكنه خيط آمن. ما هو Objective-C ، هو تعيين قفل ، لذلك فقط مؤشر الترابط الفعلي يمكن الوصول إلى المتغير ، طالما يتم تنفيذ واضعة setter / getter.

مثال مع MRC من خاصية مع ivar _internal:

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

إذن هذان الأخيرين هما نفس:

@property(atomic, retain) UITextField *userName;

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

من ناحية أخرى ، لا يضيف أي شيء إلى الشفرة. لذلك يتم مؤشر الترابط الآمن فقط إذا قمت برمز آلية الأمان بنفسك.

@property(nonatomic, retain) UITextField *userName;

لا يجب كتابة الكلمات الرئيسية على أنها سمة الخاصية الأولى على الإطلاق.

لا تنسَ ، هذا لا يعني أن الملكية ككل آمنة للخيط. فقط استدعاء الأسلوب من أداة ضبط / getter. ولكن إذا كنت تستخدم أداة ضبط ، وبعد ذلك تخطى في نفس الوقت خيوطين مختلفتين ، يمكن أن تكون مكسورة أيضًا!


أسهل إجابة أولاً: لا يوجد فرق بين المثالين الثاني والثاني. بشكل افتراضي ، يتم accessors الخاصية الذرية.

ستستخدم الموصلات الذرية في بيئة غير مجمعة (أي عند استخدام الاحتفاظ / الإفراج / autorelease) قفلًا لضمان عدم تعطل موضوع آخر مع الإعداد الصحيح / الحصول على القيمة.

راجع قسم " الأداء والتخييط " في وثائق Objective-C 2.0 من Apple للحصول على مزيد من المعلومات وللاعتبارات الأخرى عند إنشاء تطبيقات متعددة المسارات.


الأخيرين متطابقان. "الذري" هو السلوك الافتراضي ( لاحظ أنه ليس في الواقع كلمة رئيسية ؛ يتم تحديده فقط من خلال عدم وجود atomic تم إضافتها ككلمة رئيسية في الإصدارات الحديثة من llvm / clang).

إذا افترضنا أنك تقوم بتوزيع تطبيقات الطريقة ، فإن الذرية غير الذرية تعمل على تغيير الشفرة المتولدة. إذا كنت تكتب محدداتك / أجسامك ، فإن الذري / غير المادي / الاحتفاظ / التنازل / النسخ هي مجرد استشارية. (ملاحظة:synthesize هو الآن السلوك الافتراضي في الإصدارات الحديثة من LLVM. ليس هناك حاجة أيضًا إلى إعلان متغيرات الحالة ؛ سيتم تصنيعها تلقائيًا أيضًا ، وسيكون لها _ مضافًا إلى اسمها لمنع الوصول المباشر غير المقصود).

باستخدام "atomic" ، سيضمن المُنَظِّم / المترجم المركب أن القيمة الكاملة يتم إرجاعها دائمًا من الـ getter أو التي يقوم بتعيينها المُحدد ، بغض النظر عن نشاط الضبط على أي مؤشر ترابط آخر. بمعنى ، إذا كان مؤشر ترابط A في منتصف برنامج getter بينما يستدعي مؤشر الترابط B أداة الإعداد ، فسيتم إرجاع قيمة قابلة للتطبيق فعلية - كائن تم تعيينه تلقائيًا - على الأرجح - إلى المتصل في A.

في غير nonatomic ، لا يتم تقديم مثل هذه الضمانات. وبالتالي ، فإن nonatomic أسرع بشكل كبير من "ذري".

ما لا تفعله "الذري" هو تقديم أي ضمانات حول سلامة الخيط. إذا كان مؤشر الترابط A يتصل بـ getter بشكل متزامن مع مؤشر الترابط B و C باستدعاء المُؤلف بقيم مختلفة ، فقد يحصل مؤشر الترابط A على أي واحدة من القيم الثلاث التي تم إرجاعها - التي تم استدعائها قبل أي مستقر أو أي من القيم التي تم تمريرها إلى المستويين في B و C. وبالمثل ، قد ينتهي الأمر الكائن مع القيمة من B أو C ، أي وسيلة لمعرفة ذلك.

ضمان سلامة البيانات - واحدة من التحديات الرئيسية للبرمجة متعددة الخيوط - يتم تحقيقها عن طريق وسائل أخرى.

إضافة إلى هذا:

كما لا تضمن atomicity خاصية واحدة سلامة الصفحات عندما تكون هناك عدة خصائص تابعة قيد التشغيل.

يعتبر:

 @property(atomic, copy) NSString *firstName;
 @property(atomic, copy) NSString *lastName;
 @property(readonly, atomic, copy) NSString *fullName;

في هذه الحالة ، يمكن إعادة تسمية مؤشر ترابط الكائن عن طريق استدعاء setFirstName: ثم استدعاء setLastName: في هذه الأثناء ، قد يستدعي مؤشر ترابط B اسم fullName بين الاستدعاءات اثنين من مؤشر ترابط A وسيتلقى الاسم الأول الجديد المقترن باسم الأخير القديم.

لمعالجة هذا ، تحتاج إلى نموذج معاملات . أي نوع آخر من المزامنة و / أو الاستبعاد الذي يسمح لأحد باستبعاد الوصول إلى fullName أثناء تحديث الخصائص التابعة.


بعد قراءة العديد من المقالات ، نشر وإجراء تطبيقات تجريبية للتحقق من خصائص الخاصية المتغيرة ، قررت أن أجمع كل معلومات السمات معًا:

  1. atomic // الافتراضي
  2. nonatomic
  3. strong = retain / الافتراضي
  4. weak = unsafe_unretained
  5. retain
  6. assign // الافتراضي
  7. unsafe_unretained
  8. copy
  9. readonly
  10. readwrite // Default

في المقالة ، يمكنك العثور على جميع السمات المذكورة أعلاه ، والتي ستُساعدك بالتأكيد.

  1. atomic

    • يعني atomic مؤشر ترابط واحد فقط الوصول إلى متغير (نوع ثابت).
    • atomic هو موضوع آمن.
    • لكنه بطيء في الأداء
    • atomic هو السلوك الافتراضي
    • ستستخدم الموصلات الذرية في بيئة غير مجمعة (أي عند استخدام الاحتفاظ / الإفراج / autorelease) قفلًا لضمان عدم تعطل موضوع آخر مع الإعداد الصحيح / الحصول على القيمة.
    • انها ليست في الواقع كلمة رئيسية.

    مثال:

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

    • يعني nonatomic الوصول إلى مؤشر ترابط متعددة متغير (نوع الديناميكي).
    • غير nonatomic هو الخيط غير آمن.
    • لكنها سريعة في الأداء
    • غير nonatomic ليس السلوك الافتراضي. نحن بحاجة إلى إضافة الكلمة الأساسية غير nonatomic في سمة الخاصية.
    • قد ينتج عن ذلك سلوكًا غير متوقع ، عند وصول عمليتين مختلفتين (مؤشرات الترابط) إلى نفس المتغير في نفس الوقت.

    مثال:

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

هذا موضح في documentation Apple ، ولكن فيما يلي بعض الأمثلة على ما يحدث بالفعل. لاحظ أنه لا توجد كلمة مفتاحية "ذرية" ، إذا لم تقم بتحديد "nonatomic" ، فإن الخاصية تكون ذرية ، لكن تحديد "ذري" بشكل صريح سيؤدي إلى حدوث خطأ.

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

في الأساس ، يجب أن يتخذ الإصدار الذري قفلًا لضمان سلامة الخيط ، كما أنه يؤدي أيضًا إلى ارتطام عدد المرات على الكائن (وحساب عدد autorelease لموازنته) بحيث يكون الكائن مضمونًا لوجود المتصل ، وإلا فهناك هو شرط سباق محتمل إذا كان هناك مؤشر ترابط آخر يضبط القيمة ، مما يؤدي إلى انخفاض عدد مرات الظهور إلى 0.

هناك في الواقع عدد كبير من المتغيرات المختلفة لكيفية عمل هذه الأشياء اعتمادًا على ما إذا كانت الخصائص قيمًا أو كائنات قياسية ، وكيف يتفاعل ، أو نسخ ، أو قراءًا ، أو غير مادية ، وما إلى ذلك. بشكل عام ، فإن آلات التوليف الخاصة بالملكية تعرف فقط كيفية القيام "بالشكل الصحيح" لجميع المجموعات.


يتم بالفعل تعريف بناء الجملة والدلالات بشكل جيد من خلال إجابات ممتازة أخرى لهذا السؤال. ولأن التنفيذ والأداء لا يتم تفصيلهما بشكل جيد ، فسوف أقوم بإضافة جوابي.

ما هو الفرق الوظيفي بين هؤلاء الثلاثة؟

كنت دائما اعتبار الذري الافتراضي الافتراضي. على مستوى التجريد نعمل في ، باستخدام الخصائص الذرية لفئة كوسيلة لتحقيق سلامة الصفحات 100 ٪ هو حالة الزاوية. للحصول على برامج multithreaded صحيح صحيح ، من شبه المؤكد تدخل من مبرمج. وفي الوقت نفسه ، لم يتم بعد تفصيل خصائص الأداء والتنفيذ بالتفصيل. بعد أن كتبت بعض البرامج ذات مؤشرات nonatomic كبيرة على مر السنين ، كنت قد أعلنت nonatomic بأنها غير nonatomic طوال الوقت لأن الذرات لم تكن معقولة لأي غرض. خلال مناقشة تفاصيل الخصائص الذرية وغير الذرية هذه المسألة ، واجهت بعض التنميط واجه بعض النتائج الغريبة.

إعدام

حسنا. أول شيء أود أن أوضحه هو أن تطبيق القفل محدد بالتطبيق ومستخلص. يستخدم لويس @synchronized(self) في مثاله - لقد رأيت هذا كمصدر مشترك للالتباس. لا يستخدم @synchronized(self) بالفعل @synchronized(self) ؛ ويستخدم أقفال تدور مستوى الكائن. إن التوضيح الذي @synchronized(self) لويس جيد للحصول على رسم توضيحي رفيع المستوى باستخدام @synchronized(self) جميعًا ، ولكن من المهم أن نعرف أنها لا تستخدم @synchronized(self) .

هناك اختلاف آخر هو أن الخصائص الذرية ستحافظ على / تطلق دورة الأشياء الخاصة بك داخل برنامج getter.

أداء

إليك الجزء المثير للاهتمام: يمكن أن يكون الأداء الذي يستخدم الوصول إلى الخصائص الذرية في حالات غير متناظرة (مثل الخيوط المفرد) سريعًا جدًا في بعض الحالات. في حالات أقل من مثالية ، يمكن أن تكلف استخدامات الذرات أكثر من 20 مرة من الحمل غير nonatomic . بينما كانت حالة Contested التي تستخدم 7 مؤشرات ترابط أبطأ 44 مرة للبنية ثلاثية البايت (2.2 غيغاهرتز Core i7 Quad Core، x86_64). البنية ثلاثة بايت مثالاً على خاصية بطيئة جداً.

ملاحظة جانبية مثيرة للاهتمام: كانت الواقيات التي يحددها المستخدم للبنية ثلاثية البايتات أسرع بمعدل 52 مرة من الموصلات الذرية المركبة ؛ أو 84٪ من سرعة الموصلات غير المحضرة

يمكن أن تتجاوز الكائنات الموجودة في الحالات المتنازع عليها أيضًا 50 مرة.

نظرًا لعدد عمليات التحسين والتغييرات في التطبيقات ، يصعب جدًا قياس التأثيرات في العالم الحقيقي في هذه السياقات. غالبًا ما تسمع شيئًا مثل "الوثوق بها ، ما لم تكن ملفًا شخصيًا وتجده مشكلة". نظرًا لمستوى التجريد ، من الصعب جدًا قياس التأثير الفعلي. يمكن أن يكون تقليل التكاليف الفعلية من الملفات الشخصية وقتا طويلا جدا ، وبسبب التجريدات ، غير دقيق تماما. كذلك ، يمكن ARC مقابل MRC تحدث فرقا كبيرا.

لذلك دعونا نتراجع ، لا نركز على تنفيذ عمليات الوصول إلى الممتلكات ، سنقوم بتضمين المشتبه بهم المعتادين مثل objc_msgSend ، وفحص بعض النتائج عالية المستوى للعديد من المكالمات إلى objc_msgSend في الحالات غير المتنازع عليها (القيم بالثواني):

  • MRC | غير الذرية | نفذت يدويا تنفيذها: 2
  • MRC | غير الذرية | توليف توليف: 7
  • MRC | ذرية توليف توليف: 47
  • ARC | غير الذرية | synthesized getter: 38 (ملحوظة: ARC's add ref count count here)
  • ARC | ذرية توليف توليف: 47

كما كنت قد خمنت على الأرجح ، فإن نشاط إحصاء / دورة ركوب الدراجات يعد مساهماً هاماً في الذرات وتحت ARC. قد ترى أيضًا اختلافات أكبر في الحالات المتنازع عليها.

على الرغم من أنني أهتم بالأداء ، ما زلت أقول دلالات الألفاظ! . وفي الوقت نفسه ، يعتبر الأداء أولوية منخفضة للعديد من المشاريع. ومع ذلك ، لا تعرف معرفة تفاصيل التنفيذ وتكاليف التقنيات التي تستخدمها بالتأكيد. يجب عليك استخدام التقنية المناسبة لاحتياجاتك وأغراضك وقدراتك. نأمل أن هذا سيوفر لك بضع ساعات من المقارنات ، ويساعدك على اتخاذ قرار مستنير عند تصميم برامجك.


الذري

  • هو السلوك الافتراضي
  • سيضمن إكمال العملية الحالية بواسطة وحدة المعالجة المركزية ، قبل أن تصل عملية أخرى إلى المتغير
  • ليست سريعة ، لأنها تضمن اكتمال العملية بالكامل

غير الذرية

  • ليس السلوك الافتراضي
  • أسرع (بالنسبة إلى التوليف المركب ، أي للمتغيرات التي تم إنشاؤها باستخدامproperty وsynthesize)
  • لا موضوع آمن
  • قد يؤدي إلى سلوك غير متوقع ، عند وصول عملية مختلفة اثنين نفس المتغير في نفس الوقت

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;


Atomic means only one thread can access the variable at a time (static type). Atomic is thread-safe, but it is slow.

Nonatomic means multiple threads can access the variable at same time (dynamic type). Nonatomic is thread-unsafe, but it is fast.


أفضل طريقة لفهم الفرق هي استخدام المثال التالي.

افترض أن هناك خاصية سلسلة ذرية تسمى "name" ، وإذا قمت باستدعاء [self setName:@"A"] من مؤشر الترابط A ، اتصل [self setName:@"B"] من مؤشر الترابط B ، واستدعاء [self name] من الخيط C ، ثم سيتم تنفيذ جميع العمليات على مؤشرات ترابط مختلفة تسلسلي مما يعني إذا كان مؤشر ترابط واحد يتم تنفيذ محدد أو getter ، ثم سوف تنتظر مواضيع أخرى.

هذا يجعل خاصية "الاسم" للقراءة / الكتابة آمنة ، ولكن إذا كان هناك مؤشر ترابط آخر ، D ، يستدعي [name release] نفس الوقت ، فقد ينتج عن هذه العملية تعطل بسبب عدم وجود مكالمة تعيين / استبعاد هنا. وهو ما يعني أن كائن القراءة / الكتابة آمن (ATOMIC) ، ولكن ليس مؤشر ترابط آمن كما يمكن لمؤشرات ترابط أخرى إرسال أي نوع من الرسائل إلى الكائن في نفس الوقت. يجب على المطور ضمان سلامة الصفحات لمثل هذه الأشياء.

إذا كان اسم "الخاصية" غير مذكور ، فإن كل الخيوط في المثال أعلاه - A و B و C و D ستنفذ في نفس الوقت أي نتيجة غير متوقعة. في حالة ذرية ، سيتم تنفيذ واحد من A أو B أو C أولاً ، ولكن ما زال بإمكان D تنفيذ ذلك بالتوازي.


Atomic: Ensure thread-safety by locking the thread using NSLOCK.

Non atomic: Doesn't ensure thread-safety as there is no thread-locking mechanism.


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.

لاحظ كيف تقوم الخصائص غير الذرية بتعيين قيمة الخاصية مباشرة بينما تستخدم الخاصية الذرية أقفال لحماية عملية التشغيل


Before you begin: You must know that every object in memory needs to be deallocated from memory for a new write to happen. You can't just simply write on top of something as you do on paper. You must first erase (dealloc) it and then you can write onto it. If at the moment that the erase is done (or half done) and nothing has yet been wrote (or half wrote) and you try to read it could be very problematic! Atomic and nonatomic help you treat this problem in different ways.

First read this question and then read Bbum's answer . In addition then read my summary.

atomic will ALWAYS guarantee

  • If two different people want to read and write at the same time, your paper won't just burn! --> Your application will never crash, even in a race condition.
  • If one person is trying to write and has only wrote 4 of the 8 letters to written, then no can read in the middle, the reading can only be done when all 8 letters is written --> No read(get) will happen on 'a thread that is still writing', ie if there are 8 bytes to bytes to be written, and only 4 bytes are written——up to that moment, you are not allowed to read from it. But since I said it won't crash then it would read from the value of an autoreleased object.
  • If before writing you have erased that which was previously written on paper and then someone wants to read you can still read. ماذا؟ You will be reading from something similar to Mac OS Trash bin ( as Trash bin is not still 100% erased...it's in a limbo) ---> If ThreadA is to read while ThreadB has already dealloced to write, you would could either get value from the final fully written value by ThreadB or get something from autorelease pool.

Retain counts are the way in which memory is managed in Objective-C. When you create an object, it has a retain count of 1. When you send an object a retain message, its retain count is incremented by 1. When you send an object a release message, its retain count is decremented by 1. When you send an object an autorelease message , its retain count is decremented by 1 at some stage in the future. If an objectʼs retain count is reduced to 0, it is deallocated.

  • Atomic doesn't guarantee thread safety, though its useful for achieving thread safety. Thread Safety is relative to how you write your code/ which thread queue you are reading/writing from. It only guarantees non-crashable multithreading.

Wait what?! Are multithreading and thread safety different?

نعم فعلا. Multithreading means: multiple threads can read a shared piece of data at the same time and we will not crash, yet it doesn't guarantee that you aren't reading from a non-autoreleased value. With thread safety, it's guaranteed that what you read is not auto-released. The reason that we don't make everything atomic by default is, because there is a performance cost and for most things don't really need thread safety. A few parts of our code need it and for those few parts we need to write our code in a thread safe way using locks, mutex or synchronization.

nonatomic

  • Since there is no such thing like Mac OS Trash Bin, then nobody cares whether or not you always get a value (<-- This could potentially lead to a crash), nor anybody cares if someone tries to read halfway through you writing (although halfway writing in memory is very different from halfway writing on paper, on memory it could give you a crazy stupid value from before, while on paper you only see half of what's been wrote) --> Doesn't guarantee to not crash, because it doesn't use autorelease mechanism.
  • Doesn't guarantee full written values to be read!
  • Is faster than atomic

Overall they are different in 2 aspects:

  • Crashing or not because of having or not having autorelease pool.

  • Allowing to be read right in the middle of a 'not yet finished write or empty value' or not allowing and only allowing to read when the value is fully written.







atomic