[Ios] ما الفرق بين السمات الذرية وغير الذرية؟


Answers

هذا موضح في 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.

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

Question

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

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

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




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

انها تضمن فقط سلامة الخيط. لا يضمن ذلك. ما أعنيه هو أنك تستأجر سائقًا خبيرًا لسيارتك ، ولكن هذا لا يضمن أن السيارة لن تلبي أي حادث. ومع ذلك ، لا يزال الاحتمال أدنى.

ذرية - لا يمكن تقسيمها ، لذلك من المتوقع أن تكون النتيجة. مع nonatomic - عندما يصل مؤشر ترابط آخر إلى منطقة الذاكرة يمكن تعديله ، لذلك تكون النتيجة غير متوقعة.

كود الحديث:

جعل الذرية الثرية والواضع من موضوع الملكية آمنة. على سبيل المثال إذا كنت قد كتبت:

self.myProperty = value;

هو موضوع آمن.

[myArray addObject:@"Abc"] 

ليس موضوع آمن.




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

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




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.

مثال مع 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. ولكن إذا كنت تستخدم أداة ضبط ، وبعد ذلك تخطى في نفس الوقت خيوطين مختلفتين ، يمكن أن تكون مكسورة أيضًا!




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.

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




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

  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;
    



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

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

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

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

في سياقنا:

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

أين تستخدم atomic :

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

تداعيه atomic :

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

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

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




ذرية:

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

إذا كنت تتخيل الوظيفة التالية التي تحدث على موضوعين في وقت واحد يمكنك أن ترى لماذا لن تكون النتائج جميلة.

-(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 ، فإنه لا يضمن إرجاع الكائن بشكل مبدئي بشكل كامل في كل مرة.

الايجابيات: تنفيذ سريع للغاية.

سلبيات: فرص قيمة القمامة في حالة متعددة الخيوط.




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




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

افترض أن هناك خاصية سلسلة ذرية تسمى "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 تنفيذ ذلك بالتوازي.




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;




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.