是否有适合iOS的“公平”同步机制

时间:2013-01-15 22:11:23

标签: ios synchronization

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

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

3 个答案:

答案 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, ^{
    ....
    ....