我想在所有4个不同的线程完成工作时发出通知。我保留了总线程的数量,并且有一个监听器在线程完成时做了一些工作。
以下是一种安全的方法吗?
// ivars:
NSMutableArray *list;
OSSpinLock lock;
#define MAX_ALLOWED 4
- (void)someThreadedWork
{
// Iterate thru 4 different items using gcd and update
for (int x = 0; x < MAX_ALLOWED; ++x)
{
dispatch_async(some_queue, ^{
// Do some work.. once done,
[self updateCount:ix];
});
}
}
- (void)updateCount:(NSInteger)newCount
OSSpinLockLock(&lock);
{
[list addObject:[NSNumber numberWithInt:newCount]];
if ([list count] == MAX_ALLOWED)
{
_allValuesUpdatedAt = [NSDate date];
}
}
OSSpinLockUnlock(&lock);
}
- (void)observeValueForKeyPath:(NSString*)keyPath ofObject:(id)object
change:(NSDictionary*)change context:(void*)context
{
// When I get the 'allItemsUpdatedAt' event, I will perform some other work
}
- (id)init {
if (self = [super init])
{
// there is a corresponding removeObserver in the dealloc
list = [[NSMutableArray alloc] init];
[anInstance addObserver:self
forKeyPath:@"allItemsUpdatedAt"
options:NSKeyValueObservingOptionNew
context:NULL];
}
return self;
}
答案 0 :(得分:1)
HachiEthan关于dispatch_async的评论完全正确。如果您使用dispatch_group_async,那么您根本不需要任何锁定,也不必跟踪当前正在运行的线程。它会为你做所有这些。
请参阅“并发编程指南”中的"Waiting on Groups of Queued Tasks",以获得更快,更简单,更强大且能耗更低的方法来解决此问题。另请参阅同一文档中的“从线程迁移”以了解如何将基于线程的系统转换为基于队列的系统。
答案 1 :(得分:0)
以下是一些事情:
红旗:您更改了锁内_allValuesUpdatedAt
的值,但可能会在其他位置“读取”其值...(例如,任何人都在观察属性{{1}除非你的allValuesUpdatedAt
属性也受同一个allValuesUpdatedAt
实例的保护,否则你会遇到问题。 (编辑:同样,你的上面的代码没有保留NSDate,所以它会在某个时候自动释放。)
如果您使用&lock
并将其传递给串行队列,则您不需要使用自旋锁来更新dispatch_async
中的值,前提是{ {1}}方法仅由从该串行队列运行的代码访问。 (注意:您仍然需要保护对list
)
如果需要从其他代码(例如主线程)访问updateCount:
,那么是的,您将需要某种锁定,就像您拥有的那样。
编辑:保留你拥有的大部分内容,但要解决红旗问题
allValuesUpdatedAt