gpt4 book ai didi

objective-c - NSLock + 原子属性 vs 非原子

转载 作者:太空狗 更新时间:2023-10-30 03:29:11 25 4
gpt4 key购买 nike

我是 Objective-C 的新手。如果我有一个类属性可能会在 API 调用等异步事件期间被修改,那么确保在其他人访问属性时更改属性的最佳方法是什么线程不会导致崩溃?

据我所知,我有两个选择:

1) NSLock + 原子属性

...但在这种情况下,我似乎必须为每次读写锁定属性,这对我来说会破坏将其设置为原子的目的。

2) 非原子性质

我也可以将它设置为非原子的,但我想我必须在主线程上进行所有读/写。有没有办法通过 API 调用来做到这一点?成功的 API 响应后对委托(delegate)的回调是在为该 API 调用打开的线程上,还是在主线程上?如果它在不同的线程上,我可以把它放回主线程吗?具体来说,我担心 NSArray 在另一个线程循环通过它时发生变化。

这样做的最佳方法是什么?

最佳答案

我想拿贾斯汀的选项“dispatch APIs”作为一个简短的例子:

通过在专用串行队列上执行所有访问,可以使对共享资源的并发访问变得安全,我们称之为“sync_queue”。

这个“sync_queue”可能是类的私有(private)队列,其 ivars 是您要修改的资源。

您现在可以定义一个读/写非原子属性,例如:

@propery (nonatomic) NSArray* array;

写入 访问可以如下所示实现:

- (void) setArray:(NSArray* newValue) 
{
dispatch_async(sync_queue, ^{
_array = newValue;
});
}

请注意,写访问是异步的。

对该属性的读取 访问将按如下方式实现:

- (NSArray*) array:(NSArray* value) 
{
if (dispatch_get_specific(SyncQueueID) == sync_queue_id)) {
return _array;
}
else {
__block NSArray* result = nil;
dispatch_sync(_sync_queue, ^{
result = _array;
});
return result;
}
}

与写入访问不同,读取访问需要同步。该方法还必须检查当前执行上下文是否已经是 sync_queue 或同步队列的子级或任何孙子级 - 否则,读取访问将导致死锁。

为了识别当前执行上下文,我们使用函数 dispatch_queue_set_specific() 将特定标识符与同步队列关联起来。创建它时。稍后我们使用 dispatch_get_specific从当前队列或从父队列或任何祖父队列获取此标识符。如果它返回这个特定的标识符,则该方法分别在子队列或任何孙子队列的同步队列上执行。如果是,该方法会立即返回值。否则,它会在同步队列上进行同步调度。

备注:

如果共享资源将被 UIKit 访问,则 sync_queue 应为主队列。

关于objective-c - NSLock + 原子属性 vs 非原子,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/17518846/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com