我正在创建一个阻塞队列,由大约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;
}那么程序就不会死锁,然而,当我重新获得锁的时候,另一个worker已经将我需要的对象出队了。关于如何使NSCondition递归,您有什么想法吗?
发布于 2012-02-03 23:01:17
我通常使用以下模式:
-(int)primitiveSize
{
return [_queue size];
}在ObjC中以primitive为前缀的方法(来自核心数据命名传统)表明,它们没有副作用,没有有趣的业务,没有转换,只需给我值。通过这种方式,您可以在已经获得锁的情况下使用primitiveSize,而无需放弃封装。
这比创建递归互斥锁BTW快得多。
发布于 2014-02-13 07:49:30
我实现了一个替代NSCondition类的插件,它实现了一个递归互斥锁:https://github.com/bradley219/NSRecursiveCondition
https://stackoverflow.com/questions/9130250
复制相似问题