在释放时读取弱指针是否安全?
Is it safe to read a weak pointer while it's being deallocated?
从与释放对象不同的线程读取非原子弱指针是否安全?
一般来说,我知道只要可能同时进行访问,属性就应该是原子的,其中至少有一个是写操作。但是我不得不怀疑ARC的写操作(将指针设置为nil)是否有某种特殊之处。否则,我会期望看到更多关于这个可能问题的警告。也许弱指针是隐式原子的?
很安全。访问弱指针和归零弱指针在spinlock_lock和spinlock_unlock之间。
看看运行时源码
http://opensource.apple.com/source/objc4/objc4-646/runtime/NSObject.mm
访问弱指针
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;
}
归零弱指针
void
objc_object::sidetable_clearDeallocating()
{
SideTable *table = SideTable::tableForPointer(this);
// clear any weak table items
// clear extra retain count and deallocating bit
// (fixme warn or abort if extra retain count == 0 ?)
spinlock_lock(&table->slock);
RefcountMap::iterator it = table->refcnts.find(this);
if (it != table->refcnts.end()) {
if (it->second & SIDE_TABLE_WEAKLY_REFERENCED) {
weak_clear_no_lock(&table->weak_table, (id)this);
}
table->refcnts.erase(it);
}
spinlock_unlock(&table->slock);
}
和对象解除分配流程
从与释放对象不同的线程读取非原子弱指针是否安全?
一般来说,我知道只要可能同时进行访问,属性就应该是原子的,其中至少有一个是写操作。但是我不得不怀疑ARC的写操作(将指针设置为nil)是否有某种特殊之处。否则,我会期望看到更多关于这个可能问题的警告。也许弱指针是隐式原子的?
很安全。访问弱指针和归零弱指针在spinlock_lock和spinlock_unlock之间。
看看运行时源码 http://opensource.apple.com/source/objc4/objc4-646/runtime/NSObject.mm
访问弱指针
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;
}
归零弱指针
void
objc_object::sidetable_clearDeallocating()
{
SideTable *table = SideTable::tableForPointer(this);
// clear any weak table items
// clear extra retain count and deallocating bit
// (fixme warn or abort if extra retain count == 0 ?)
spinlock_lock(&table->slock);
RefcountMap::iterator it = table->refcnts.find(this);
if (it != table->refcnts.end()) {
if (it->second & SIDE_TABLE_WEAKLY_REFERENCED) {
weak_clear_no_lock(&table->weak_table, (id)this);
}
table->refcnts.erase(it);
}
spinlock_unlock(&table->slock);
}
和对象解除分配流程