我正在创建一个阻塞队列,同时由大约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
递归的任何想法吗?
答案 0 :(得分:1)
我通常使用以下模式:
-(int)primitiveSize
{
return [_queue size];
}
在ObjC中以primitive
为前缀的方法(来自核心数据命名传统)表明它们没有副作用,没有有趣的业务,没有转换,只是给予我价值。这样,您可以在已经获得锁定而不放弃封装的情况下使用primitiveSize
。
这比创建递归互斥体BTW要快得多。
答案 1 :(得分:0)
我已经为实现递归互斥锁的NSCondition类实现了一个替代品:https://github.com/bradley219/NSRecursiveCondition