想象一下,您想在 iOS 应用程序的后台做很多事情,但您正确地对其进行了编码,以便您创建线程(例如使用 GCD)来执行此后台活动。
现在,如果您需要在某些时候编写更新变量,但此更新可能发生或您创建的任何线程发生。
您显然想保护该变量,您可以使用关键字@synchronized
为您创建锁,但这里有一个问题(摘自 Apple 文档)
该
@synchronized()
指令锁定一段代码供单个线程使用。其他线程被阻塞,直到线程退出受保护的代码——也就是说,当执行继续超过@synchronized()
块中的最后一条语句时。
这意味着如果您同步一个对象并且两个线程同时写入它,即使主线程也会阻塞,直到两个线程都完成写入数据。
将展示所有这些的代码示例:
// Create the background queue
dispatch_queue_t queue = dispatch_queue_create("synchronized_example", NULL);
// Start working in new thread
dispatch_async(queue, ^
{
// Synchronized that shared resource
@synchronized(sharedResource_)
{
// Write things on that resource
// If more that one thread access this piece of code:
// all threads (even main thread) will block until task is completed.
[self writeComplexDataOnLocalFile];
}
});
// won’t actually go away until queue is empty
dispatch_release(queue);
所以问题很简单:如何克服这个问题?除了我们知道在这种情况下不需要阻塞的主线程之外,我们如何安全地在所有线程上添加锁?
编辑澄清
正如你们中的一些人评论的那样,只有两个试图获取锁的线程应该阻塞,直到它们都完成,这似乎是合乎逻辑的(这显然是我在使用同步时最初的想法)。
然而,在实际情况下测试,情况似乎并非如此,主线程似乎也受到锁的影响。
我使用这种机制在单独的线程中记录事物,这样 UI 就不会被阻塞。但是当我进行密集的日志记录时,UI(主线程)显然受到很大影响(滚动不那么流畅)。
所以这里有两个选择:要么后台任务太繁重以至于连主线程都会受到影响(我对此表示怀疑),或者同步在执行锁定操作时也会阻塞主线程(我正在重新考虑)。
我将使用 Time Profiler 进一步挖掘。