1

我正在创建一个阻塞队列,由大约 10 个工作线程同时访问。队列的基本实现是这样的:

-(void) enqueue:(__strong id)value
{
    [_mutex lock];

    while ([self size] == _maxSize) {
        [_mutex wait];
    }

    [_queue enqueue:value];
    [_mutex signal];
    [_mutex unlock];
}

-(id) dequeue
{    
    [_mutex lock];

    while ([self isEmpty]) {
        [_mutex wait];
    }

    id value = [_queue dequeue];
    [_mutex broadcast];

    [_mutex unlock];
    return value;
}

_mutex一个在哪里NSCondition。问题来自-isEmpty-size方法:

-(int) size
{
    @try {
        [_mutex lock];

        return [_queue size];
    }
    @finally {
        [_mutex unlock];        
    }
}

-(BOOL) isEmpty
{
    @try {
        [_mutex lock];

        return [_queue isEmpty];
    }
    @finally {    
        [_mutex unlock];
    }
}

因为它们需要对互斥锁进行锁定以确保没有数据损坏,所以它会使程序陷入死锁,因为NSCondition不会递归锁定。但是,如果我将实现更改为以下内容:

-(void) enqueue:(__strong id)value
{
    while ([self size] == _maxSize) {
        [_mutex lock];
        [_mutex wait];
        [_mutex unlock];
    }

    [_mutex lock];
    [_queue enqueue:value];
    [_mutex signal];
    [_mutex unlock];
}

-(id) dequeue
{
    while ([self isEmpty]) {
        [_mutex lock];
        [_mutex wait];
        [_mutex unlock];
    }

    [_mutex lock]; // when I require the lock here, another thread has already dequeued the object
    id value = [_queue dequeue];
    [_mutex broadcast];

    [_mutex unlock];
    return value;
}

然后程序不会死锁,但是,当我重新获得锁时,另一个工作人员已经将我需要的对象出队。关于如何进行NSCondition递归的任何想法?

4

2 回答 2

1

我通常使用以下模式:

-(int)primitiveSize
{
  return [_queue size];
}

以 ObjC为前缀的方法primitive(来自 Core Data 命名传统)表明它们没有副作用,没有有趣的业务,没有转换,只是给我的价值。这样,您可以primitiveSize在已经获得锁而不放弃封装的情况下使用。

这比创建递归互斥锁要快得多 BTW。

于 2012-02-03T15:01:16.757 回答
0

我已经实现了实现递归互斥锁的 NSCondition 类的直接替换:https ://github.com/bradley219/NSRecursiveCondition

于 2014-02-12T23:49:30.463 回答