我有一个应用程序倾向于在后台线程中执行大量数据库活动(下载大型数据库更新),而且这个过程经常“饿死” UI 线程——我知道数据库是不定期发布的,但是@synchronized
使用的机制不是“公平的”,并且允许后台线程立即重新获取锁。
是否有另一种相当有效且得到良好支持(并且不太难改造)(并且“公平”)的机制可以代替使用?
我有一个应用程序倾向于在后台线程中执行大量数据库活动(下载大型数据库更新),而且这个过程经常“饿死” UI 线程——我知道数据库是不定期发布的,但是@synchronized
使用的机制不是“公平的”,并且允许后台线程立即重新获取锁。
是否有另一种相当有效且得到良好支持(并且不太难改造)(并且“公平”)的机制可以代替使用?
我无法重现您的问题。在这里,我有一个简单的程序(尽管在 mac 上运行),基于@synchronized
pthreads,它清楚地表明它@synchronized
按预期工作,假设你释放你的锁:
void *backgroundThread(void *data)
{
while (true)
{
@synchronized (globalMutex)
{
usleep(USEC_PER_SEC / 3);
}
}
return NULL;
}
int main()
{
pthread_t bgThread = NULL;
globalMutex = [NSObject new];
pthread_create(&bgThread, NULL, &backgroundThread, NULL);
NSTimeInterval lastTime = [[NSDate date] timeIntervalSinceReferenceDate];
while (true)
{
@synchronized (globalMutex)
{
NSTimeInterval elapsed = [[NSDate date] timeIntervalSinceReferenceDate] - lastTime;
NSLog(@"Main Thread 'came up for air' after %lf seconds", elapsed);
lastTime += elapsed;
}
}
}
输出:
TestProj[1494:303] 主线程在 0.000015 秒后“出现” TestProj[1494:303] 主线程在 0.003136 秒后“出现” TestProj[1494:303] 主线程在 0.000637 秒后“出现” TestProj[1494:303] 主线程在 0.000610 秒后“出现” TestProj[1494:303] 主线程在 0.000697 秒后“出现” TestProj[1494:303] 主线程在 0.000576 秒后“出现” TestProj[1494:303] 主线程在 0.000571 秒后“出现” TestProj[1494:303] 主线程在 0.337343 秒后“出现” TestProj[1494:303] 主线程在 0.335533 秒后“出现” TestProj[1494:303] 主线程在 0.335253 秒后“出现” TestProj[1494:303] 主线程在 0.335309 秒后“出现” TestProj[1494:303] 主线程在 0.335367 秒后“出现” TestProj[1494:303] 主线程在 0.335223 秒后“出现” TestProj[1494:303] 主线程在 0.335754 秒后“出现” TestProj[1494:303] 主线程在 0.335271 秒后“出现” TestProj[1494:303] 主线程在 0.335211 秒后“出现” TestProj[1494:303] 主线程在 0.334555 秒后“出现” TestProj[1494:303] 主线程在 0.335245 秒后“出现” TestProj[1494:303] 主线程在 0.335203 秒后“出现” TestProj[1494:303] 主线程在 0.335262 秒后“出现” TestProj[1494:303] 主线程在 0.335252 秒后“出现” TestProj[1494:303] 主线程在 0.335667 秒后“出现” TestProj[1494:303] 主线程在 0.335278 秒后“出现” TestProj[1494:303] 主线程在 0.335309 秒后“出现”
因此,除非您没有正确释放锁,否则这@synchronized
正是您在这种情况下所需要的。请详细说明您的同步代码实际上是什么样的,以便我们为您提供更多帮助。
据我了解,@synchronized 是 一种创建互斥锁的便捷方式。它不必是“公平的”。
我建议阅读有关GCD的信息。它有很多有趣的东西可以将所有需要完成的工作放在队列中(这应该提供更好的资源共享)。
如果您担心阻塞您的 UI 线程,您可以为您的数据库操作创建一个串行调度队列。这将使您能够从 UI 线程排队一些 DB 操作,而不会阻塞它(工作块将被复制到堆中,存储到轮到它处理为止)。
例如,从 UI 线程,您可以:
database_queue = dispatch_queue_create("com.example.queue", NULL);
dispatch_async(database_queue, ^{
// Operations on the DB here
});
// The UI will continue responding immediately after here...
队列将一次处理每个块,提供您需要的同步 - 您只需要确保所有数据库操作都从该队列完成。
如果您确实需要等到工作确实完成,您可以在这些特定情况下将异步调用换成同步调用:
dispatch_sync(database_queue, ^{
....
....