gpt4 book ai didi

objective-c - GCD - 串行队列是否需要 `NSLock` 或内存屏障来同步工作?

转载 作者:太空狗 更新时间:2023-10-30 04:00:51 25 4
gpt4 key购买 nike

我阅读了有关 GCD 队列的 Apple 文档,开始想知道如果我让修改类型为 NSMutableArray 的实例成员在串行队列中不是线程安全的,会发生什么情况?串行队列会保证我串行执行操作,但我仍然觉得我需要做一个 @syncrhonized block 或其他技术来强制内存屏障,因为据我了解我的串行队列上的任务可以在不同的线程上调用。那是对的吗?这是一个简单的例子:

@interface Foo : NSObject

-(void)addNumber:(NSNumber*)number;
-(void)printNumbers;
-(void)clearNumbers;

@end

@implementation Foo
{
dispatch_queue_t _queue;
NSMutableArray<NSNumber*>* _numbers;
}

-(instancetype)init
{
if (self = [super init])
{
_queue = dispatch_queue_create(NULL, NULL);
_numbers = [NSMutableArray array];
}
return self;
}

-(void)addNumber:(NSNumber*)number
{
dispatch_async(_queue,
^{
[_numbers addObject:number];
});
}

-(void)printNumbers
{
dispatch_async(_queue,
^{
for (NSNumber* number in _numbers)
{
NSLog(@“%@“, number);
}
});
}

-(void)clearNumbers
{
dispatch_async(_queue,
^{
_numbers = [NSMutableArray array];
});
}
@end;

据我所知,如果我从任意线程调用成员方法,我会在这里遇到内存问题吗?或者 GCD 在底层提供了一些保证,为什么我不需要强制内存屏障?查看这些示例,我在任何地方都找不到这样的构造,但是来自 C++ 时,在锁下触摸成员变量是有意义的。

最佳答案

如果你的队列是一个串行队列,它一次只允许一个操作,不管它在哪个线程上运行。因此,如果对资源的每次访问都发生在队列中,则无需使用锁或信号量进一步保护该资源。事实上,可以使用调度队列作为锁定机制,并且对于某些应用程序,它可以工作得很好。

现在如果您的队列是并发队列,那就是另一回事了,因为多个操作可以同时在并发队列上运行。但是,GCD 提供了 dispatch_barrier_syncdispatch_barrier_async API。您通过这两个函数调用启动的操作将导致队列在执行您的 block 之前等待所有其他操作完成,然后在该 block 完成之前不允许运行任何更多操作。通过这种方式,它可以暂时使队列的行为类似于串行队列,甚至允许将并发队列用作一种锁定机制(例如,允许通过普通的 dispatch_sync 读取资源)调用,但通过 dispatch_barrier_async 进行写入。如果读取非常频繁而写入非常不频繁,这可以很好地执行)。

关于objective-c - GCD - 串行队列是否需要 `NSLock` 或内存屏障来同步工作?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/48628952/

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