问题描述
我正在构建一个多线程应用程序,该应用程序可以从其中多个线程写入包括主线程的sqlite3数据库.我声明了一个用于互斥量的静态公共变量:
I'm building a multithreaded application, from which more than one thread can write to an sqlite3 database including the main thread. I declared a static public variable to be used for the mutex:
@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指令的变量来锁定写入数据库的部分.
and inside each method that should write to a database I'm using that variable with the @synchronized directive to lock the section that write to the database.
- (void)method1FromClass1 {
@synchronized ([Application submitChangesLock]) {
// write to the database here...
}
}
- (void)method2FromClass2 {
@synchronized ([Application submitChangesLock]) {
// write to the database here...
}
}
并且一切正常,但是有时当从主线程调用这些方法中的任何一个时,它冻结,等待互斥锁再次解锁,但事实并非如此,问题在于,这仅发生在主线程的某些调用上而且写入数据库的代码绝对是有限的,因此我无法确定为什么主线程一直等待互斥体被解锁,以及为什么它没有首先被解锁.
and everything worked fine but sometimes when any of those methods gets called from the main thread it freezes waiting for the mutex to be unlocked again but it didn't and the problem is that this only occurs on some calls from the main thread and the code that writes to the database is definitely finite so I could not determine why the main thread keeps waiting for mutex to be unlocked and why it's not getting unlocked on the first place.
注意:该互斥锁没有阻塞其他线程,只有主线程处于打开状态.
Note: none of the other threads got blocked by this mutex, only the main on.
我尝试使用performSelectorOnMainThread:waitUntilDone替换@synchronized指令:
I tried to replace the @synchronized directive using the performSelectorOnMainThread:waitUntilDone:
- (void)writeToDatabase {
// write to the database here...
}
- (void)method2FromClass2 {
[self performSelectorOnMainThread:@selector(writeToDatabase) withObject:nil waitUntilDone:YES];
}
它的工作正常,但我试图避免在主线程上施加如此大的负载,以免阻止用户交互.
and it's working just fine but I'm trying to avoid so much load on the main thread not to block the user interaction.
任何帮助将不胜感激,在此先感谢您.
Any help would be greatly appreciated, and many thanks in advance.
推荐答案
iOS中存在一些功能,可帮助您避免在简单到中等复杂的情况下处理线程/锁定.
There are features in iOS which exist to help you avoid dealing with threads/locking in simple to moderately complex situations.
如果按照deanWombourne的建议将NSOperationQueue
和setMaxConcurrentOperationCount:
设置为1,则可以将所有工作卸载到后台线程.甚至还有一个方便的类(NSInvocationOperation
),可以轻松地重用队列中现有类中的代码.
If you set up an NSOperationQueue
and setMaxConcurrentOperationCount:
to 1, as suggested by deanWombourne, you can offload all the work to a background thread. There's even a handy class (NSInvocationOperation
) to easily reuse your code from existing classes in a queue.
如果这些在后台运行的方法会影响UI中显示的内容,则您始终可以使用performSelectorOnMainThread:withObject:waitUntilDone:
进行必要的更新.
If these methods that are running in the background will affect what's appearing in the UI, you can always use performSelectorOnMainThread:withObject:waitUntilDone:
to update whatever is necessary.
如果您这样做,您将永远不会因为数据库活动而阻塞主线程.由于阻塞主线程会冻结UI,因此这绝对是处理问题的方法.
If you do it like this, you'll never be blocking your main thread with DB activity. Since blocking the main thread freezes the UI, this is definitely the way to do things.
这篇关于互斥锁仅在使用@synchronized指令到达其调用时才阻塞主线程的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!