0

我正在构建一个多线程应用程序,多个线程可以从中写入包括主线程在内的 sqlite3 数据库。我声明了一个用于互斥锁的静态公共变量:

@implementation Application

#pragma mark -
#pragma mark Static Initializer
static NSString * SubmitChangesLock = nil;

+ (void)initialize {
    [super initialize];
    SubmitChangesLock = [[NSString alloc] initWithString:@"Submit-Changes-Lock"];
}

+ (NSString *)submitChangesLock {
    return SubmitChangesLock;
}

@end

在每个应该写入数据库的方法中,我使用带有@synchronized 指令的变量来锁定写入数据库的部分。

- (void)method1FromClass1 {
    @synchronized ([Application submitChangesLock]) {
        // write to the database here...
    }
}

- (void)method2FromClass2 {
    @synchronized ([Application submitChangesLock]) {
        // write to the database here...
    }
}

一切正常,但有时当从主线程调用这些方法中的任何一个时,它会冻结等待互斥锁再次解锁但它没有,问题是这只发生在来自主线程和代码的某些调用上写入数据库的内容肯定是有限的,所以我无法确定为什么主线程一直在等待互斥锁被解锁,以及为什么它一开始没有被解锁。

注意:没有其他线程被这个互斥锁阻塞,只有主线程。

编辑:我尝试使用 performSelectorOnMainThread:waitUntilDone 替换 @synchronized 指令:

- (void)writeToDatabase {
    // write to the database here...
}
- (void)method2FromClass2 {
    [self performSelectorOnMainThread:@selector(writeToDatabase) withObject:nil waitUntilDone:YES];
}

它工作得很好,但我试图避免主线程上的负载过多,而不是阻止用户交互。

任何帮助将不胜感激,并提前非常感谢。

4

1 回答 1

2

iOS 中有一些功能可以帮助您避免在简单到中等复杂的情况下处理线程/锁定。

如果按照 deanWombourne 的建议设置NSOperationQueueandsetMaxConcurrentOperationCount:为 1,则可以将所有工作卸载到后台线程。甚至还有一个方便的类 ( NSInvocationOperation) 可以轻松地从队列中的现有类中重用您的代码。

如果这些在后台运行的方法会影响 UI 中显示的内容,您可以随时使用performSelectorOnMainThread:withObject:waitUntilDone:来更新任何必要的内容。

如果你这样做,你永远不会用数据库活动阻塞你的主线程。由于阻塞主线程会冻结 UI,这绝对是做事的方式。

于 2012-01-04T12:31:07.733 回答