我有一个应用程序,它倾向于在后台线程中执行大量数据库活动(下载大型数据库更新),并且这个过程经常“饿死”UI线程 - 我知道数据库正在按时发布,但使用的@synchronized
机制不是“公平”,并允许后台线程立即重新获取锁。
是否有另一种机制可以合理有效且得到良好支持(并且不太难以改造)(和“公平”)可以替代使用?
答案 0 :(得分:2)
我无法重现您的问题。在这里,我有一个基于@synchronized
和pthreads的简单程序(尽管在mac上运行),它清楚地表明@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] Main Thread 'came up for air' after 0.000015 seconds TestProj[1494:303] Main Thread 'came up for air' after 0.003136 seconds TestProj[1494:303] Main Thread 'came up for air' after 0.000637 seconds TestProj[1494:303] Main Thread 'came up for air' after 0.000610 seconds TestProj[1494:303] Main Thread 'came up for air' after 0.000697 seconds TestProj[1494:303] Main Thread 'came up for air' after 0.000576 seconds TestProj[1494:303] Main Thread 'came up for air' after 0.000571 seconds TestProj[1494:303] Main Thread 'came up for air' after 0.337343 seconds TestProj[1494:303] Main Thread 'came up for air' after 0.335533 seconds TestProj[1494:303] Main Thread 'came up for air' after 0.335253 seconds TestProj[1494:303] Main Thread 'came up for air' after 0.335309 seconds TestProj[1494:303] Main Thread 'came up for air' after 0.335367 seconds TestProj[1494:303] Main Thread 'came up for air' after 0.335223 seconds TestProj[1494:303] Main Thread 'came up for air' after 0.335754 seconds TestProj[1494:303] Main Thread 'came up for air' after 0.335271 seconds TestProj[1494:303] Main Thread 'came up for air' after 0.335211 seconds TestProj[1494:303] Main Thread 'came up for air' after 0.334555 seconds TestProj[1494:303] Main Thread 'came up for air' after 0.335245 seconds TestProj[1494:303] Main Thread 'came up for air' after 0.335203 seconds TestProj[1494:303] Main Thread 'came up for air' after 0.335262 seconds TestProj[1494:303] Main Thread 'came up for air' after 0.335252 seconds TestProj[1494:303] Main Thread 'came up for air' after 0.335667 seconds TestProj[1494:303] Main Thread 'came up for air' after 0.335278 seconds TestProj[1494:303] Main Thread 'came up for air' after 0.335309 seconds
因此,除非您没有正确释放锁定,否则{J}}正是您在此方案中所需要的。请详细说明您的同步代码实际上是什么样的,以便我们为您提供更多帮助。
答案 1 :(得分:1)
因为我不知所措并且@synchronized是a convenient way to create mutex locks。它不一定是“公平的”。
我建议您阅读GCD。它有很多有趣的东西可以将所有需要完成的工作放在队列中(这应该提供更好的资源共享)。
答案 2 :(得分:0)
如果您担心阻止UI线程,可以为数据库操作创建一个串行调度队列。这将使您能够从UI线程排队一些数据库操作,而不会阻塞它(工作块将被复制到堆中,存储直到轮到它进行处理)。
例如,从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, ^{
....
....