1

我有一个应用程序倾向于在后台线程中执行大量数据库活动(下载大型数据库更新),而且这个过程经常“饿死” UI 线程——我知道数据库是不定期发布的,但是@synchronized使用的机制不是“公平的”,并且允许后台线程立即重新获取锁。

是否有另一种相当有效且得到良好支持(并且不太难改造)(并且“公平”)的机制可以代替使用?

4

3 回答 3

2

我无法重现您的问题。在这里,我有一个简单的程序(尽管在 mac 上运行),基于@synchronizedpthreads,它清楚地表明它@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正是您在这种情况下所需要的。请详细说明您的同步代码实际上是什么样的,以便我们为您提供更多帮助。

于 2013-01-15T22:37:25.283 回答
1

据我了解,@synchronized 是 一种创建互斥锁的便捷方式。它不必是“公平的”。

我建议阅读有关GCD的信息。它有很多有趣的东西可以将所有需要完成的工作放在队列中(这应该提供更好的资源共享)。

于 2013-01-15T22:16:43.107 回答
0

如果您担心阻塞您的 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, ^{
    ....
    ....
于 2013-01-15T22:28:53.973 回答