NSCondition死锁

时间:2011-08-01 09:39:45

标签: objective-c multithreading cocoa

我正在开发一个从HTTP连接接收数据的应用程序,数据在进入时由一个或多个线程处理。我使用NSCondition允许读取器线程等待传入数据并建立连接当数据可用时,线程广播它们但我一直陷入僵局,我无法理解为什么。我要么误解了NSCondition是如何工作的,要么是我花了很长时间盯着它看,我错过了其他的东西。这是代码:

// lock = NSCondition ivar
// position = long long ivar
// writeDataToFile performs no locking but just writes the data to an NSHandle and logs in debug

- (void)connection:(NSURLConnection*)connection didReceiveData:(NSData*)data {
    [condition lock];
    @try {
        [self writeDataToFile:data];
        position += [data length];
        hasMoreData = YES;
    } @finally {
        [condition broadcast];
        [condition unlock];
    }
}

- (void)connection:(NSURLConnection*)connection didReceiveResponse:(NSURLResponse*)response {

    NSHTTPURLResponse *httpResponse = (NSHTTPURLResponse*)response;
    int statusCode = [httpResponse statusCode];
    requestSuccess = (statusCode == 200);

    [condition lock];
    [condition broadcast];
    [condition unlock];
}

- (void)connection:(NSURLConnection*)connection didFailWithError:(NSError*)error {
    [condition lock];
    hasMoreData = YES;
    [condition broadcast];
    [condition unlock];
}

- (void)waitForData {
    [condition lock];
    @try {
        while( !hasMoreData ) {
            [condition wait];
        }
    } @finally {
        hasMoreData = NO;
        [condition unlock];
    }
}

现在这通常有效但偶尔我会看到应用程序挂起并且示例显示一个线程正在等待条件,另一个等待获取waitForData中的锁定而另一个等待获取锁定连接:didReceiveData ”。

我的理解是[condition wait]调用以原子方式解锁它的内部互斥锁并等待条件,因此多个等待线程不应阻止connection:didReceiveData:线程获取并广播该条件。

我错过了什么?

谢谢, Ĵ

2 个答案:

答案 0 :(得分:0)

猜猜,使用这种方法

- (void)connection:(NSURLConnection *)connection
  didFailWithError:(NSError *)error

并在此解锁条件。如果您没有收到回复,请[condition unlock];

此行未调用。所以这些都被锁定,你的应用程序挂起,所以尝试使用这个建议。

答案 1 :(得分:0)

在一天结束时,我认为使用锁是一个复杂的解决方案。在主线程上使用同步IO是一个很大的禁忌,但是在后台线程上执行它是正常的,并且很多比处理异步请求更容易。

因此,如果你在后台线程中,阻止当前线程等待IO线程的整个混乱只是一个痛苦的屁股。替换为+[NSURLConnection sendSynchronousRequest:returningResponse:error:]并完成。