0

我想在所有 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;
}
4

2 回答 2

1

HachiEthan 关于 dispatch_async 的评论是完全正确的。如果您改用 dispatch_group_async,那么您根本不需要任何锁定,也不必跟踪当前正在工作的线程。它会为你做这一切。

请参阅并发编程指南中的“等待队列任务组”,以获得更快、更简单、更健壮且能耗更低的方法来解决此问题。另请参阅同一文档中的“从线程迁移”以了解如何将基于线程的系统转换为基于队列的系统。

于 2012-08-29T20:05:21.847 回答
0

这里有几件事:

危险信号:您更改了_allValuesUpdatedAt锁内部的值,但可能会在其他地方“读取”其值......(例如,观察该属性的人allValuesUpdatedAt)所以除非您的allValuesUpdatedAt财产也受到同一个&lock实例的保护,否则您会遇到问题那里。(编辑:另外,你上面的代码没有保留 NSDate,所以它会在某个时候自动发布给你。)

如果您使用dispatch_async并将其传递给串行队列,那么您不需要该自旋锁来更新 中的值list,前提是该updateCount:方法只能由从该串行队列运行的代码访问。(注意:您仍然需要保护访问allValuesUpdatedAt

如果updateCount:确实需要从其他代码(例如主线程)访问,那么是的,您将需要某种锁,就像您拥有的那样。


编辑:保留您拥有的大部分内容,但要解决危险信号

//header:
@property (atomic, retain) NSDate *allValuesUpdatedAt;

//impl:
- (void)updateCount:(NSInteger)newCount
    OSSpinLockLock(&lock);
    {
        [list addObject:[NSNumber numberWithInt:newCount]];

        if ([list count] == MAX_ALLOWED)
        {
            //use atomic property for read/write thread-safety:
            self.allValuesUpdatedAt = [NSDate date]; 
        }
    }
    OSSpinLockUnlock(&lock);
}
于 2012-08-29T19:00:45.660 回答