weak引用變數是否安全執行緒

來源:互聯網
上載者:User

標籤:清空   編譯   and   執行   unlock   object_c   使用者   清理   修飾符   

1、在ARC出現之前,Objetive-C的記憶體管理需要手工執行release&retain操作,這些極大增加了代碼的編寫難度,同時帶來很多的crash。

   同時大量的delegate是unretain的,如果忘記在dealloc中主動設定為空白,將帶來野指標的隱患。由於dealloc是一個線程不安全的方法

   在MRC的環境下面,如果一個對象在一個線程中正在釋放過程當中,這個對象在另外一個線程收到通知,極有可能帶來Crash,

  這個取決於執行的方法中訪問的對象記憶體是否被破壞掉。

 

2、ARC出現之後帶來了weak修飾符,降低了野指標出現的機率,同時將dealloc方法進行了修改,使用者不需要主動調用[super dealloc],由編譯器插入。

   同時編譯器插入了一個cxx_dealloc的方法,這個方法真正釋放該對象持有的變數,dealloc方法只能算作即將釋放的一個回調,那麼ARC下面dealloc是怎麼執行的呢。

 

3、dealloc的方法執行

  1、一個對象執行release方法,引用計數減少1,變成0

  2、調用該對象的dealloc方法

  3、該對象dealloc方法執行完畢調用父類的dealloc方法

  4、調用NSObject的dealloc方法

  5、NSObject的dealloc方法執行_objc_rootDealloc(self);

  6、_objc_rootDealloc 中調用 object_dispose()

  7、object_dispose 中調用 objc_destructInstance()

  8、objc_destructInstance 調用 objc_clear_deallocating

  

 1 void *objc_destructInstance(id obj) 2 { 3     if (obj) { 4         Class isa_gen = _object_getClass(obj); 5         class_t *isa = newcls(isa_gen); 6  7         // Read all of the flags at once for performance. 8         bool cxx = hasCxxStructors(isa); 9         bool assoc = !UseGC && _class_instancesHaveAssociatedObjects(isa_gen);10 11         // This order is important.12         if (cxx) object_cxxDestruct(obj);13         if (assoc) _object_remove_assocations(obj);14 15         if (!UseGC) objc_clear_deallocating(obj);16     }17 18     return obj;19 }20 void objc_clear_deallocating(id obj) 21 {22     assert(obj);23     assert(!UseGC);24 25     SideTable *table = SideTable::tableForPointer(obj); /* *** THIS LINE *** */26 27     // clear any weak table items28     // clear extra retain count and deallocating bit29     // (fixme warn or abort if extra retain count == 0 ?)30     OSSpinLockLock(&table->slock);31     if (seen_weak_refs) {32     arr_clear_deallocating(&table->weak_table, obj); /* *** THIS LINE *** */33     }34     table->refcnts.erase(DISGUISE(obj)); /* *** THIS LINE *** */35     OSSpinLockUnlock(&table->slock);36 }

  在上面的objc_destructInstance代碼中,首先釋放object_cxxDestruct方法,這裡面會逐級往上移出對象的執行個體變數

  然後移除關聯對象

  第三步中清空了weak指標

  可以看出來,清除一個對象的執行個體變數是統一清理的,由下逐級往上。

  在清理weak指標的時候如何保證這個對象在dealloc收到訊息的時候還是安全執行緒的呢?

  答案下面:

    得到一個weak 指標的時候會執行下面的方法,該方法中有一個spinlock,這個鎖在清理weak指標的時候同時會用到,所以是安全執行緒的。

    也就是這個weak指標獲得的結果要麼為空白,要麼不為空白,只要不為空白,就代表這個指標指向的記憶體地區沒有被釋放掉,其對象內部的執行個體變數還是有可能被清理掉的。

    這個時候向這個指標發送訊息,不會帶來crash,但是邏輯可能異常,這種情況理論上存在。

id objc_loadWeakRetained(id *location){    id result;    SideTable *table;    spinlock_t *lock; retry:    result = *location;    if (!result) return nil;    table = SideTable::tableForPointer(result);    lock = &table->slock;    spinlock_lock(lock);    if (*location != result) {        spinlock_unlock(lock);        goto retry;    }    result = weak_read_no_lock(&table->weak_table, location);    spinlock_unlock(lock);    return result;}

  

4、參考資料

  http://stackoverflow.com/questions/30673101/is-it-safe-to-read-a-weak-pointer-while-its-being-deallocated

  http://stackoverflow.com/questions/14854635/how-can-the-objective-c-runtime-know-whether-a-weakly-referenced-object-is-still/14854977#14854977

  http://blog.sunnyxx.com/2014/04/02/objc_dig_arc_dealloc/

  

weak引用變數是否安全執行緒

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.