NSCondition:递归锁定?

时间:2012-02-03 14:32:22

标签: objective-c multithreading mutex semaphore nscondition

我正在创建一个阻塞队列,同时由大约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;
}

_mutexNSCondition的位置。问题来自-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递归的任何想法吗?

2 个答案:

答案 0 :(得分:1)

我通常使用以下模式:

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

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

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

答案 1 :(得分:0)

我已经为实现递归互斥锁的NSCondition类实现了一个替代品:https://github.com/bradley219/NSRecursiveCondition