大佬教程收集整理的这篇文章主要介绍了为什么两个不同的串行队列会在 swift 中造成死锁?,大佬教程大佬觉得挺不错的,现在分享给大家,也给大家做个参考。
我有一个自定义串行队列,在这个同步调用主队列旁边。它正在制造僵局。根据我的理解,两者都是独立的队列,因此它应该可以工作,并且(第 3 步和第 5 步)同步块都应该执行。谁能解释为什么会产生死锁?下面是我的游乐场代码。
func serialQueuetest() {
let customserialQueue = dispatchQueue(label: "com.test.dipak")
print("Step 1")
customserialQueue.async {
print("Step 2")
dispatchQueue.main.sync {
print("Step 3: InsIDe main sync queue")
}
}
print("Step 4")
customserialQueue.sync {
print("Step 5: InsIDe Custom serial Queue sync queue")
}
}
您正在阻止 main.
在第 4 步,您从 main 调用,main 将块提交到队列并等待它完成。但是到那时你已经提交了第一个块(第 1 步),它又在等待 main 释放。
编辑
请注意,CSQ 不会阻止尝试执行您提交的两个块,而是 CSQ 和 main 正在阻止彼此等待完成。我可以很容易地说明这一点如果队列中有一个 isBusy
函数,但既然没有,让我们假设有,看看下面的代码。
func serialQueueTest() {
let customserialQueue = DispatchQueue(label: "com.test.dipak")
print("Step 1")
customserialQueue.async {
print("Step 2")
// Previously
// DispatchQueue.main.sync { AAA }
// same as below pseudo code
while ( main.isBusy )
{
wait ... *without* releasing control
}
now,on main,do AAA and then proceed
print ( "****" )
print ( "CSQ will now wait for main to finish what it is doing ..." )
print ( "But note,it does not release control or do something else," )
print ( "it *blocks* until main is finished. So it deadlocks." )
}
print("Step 4")
// Previously
// customserialQueue.sync BBB
// replaced with ...
while ( csq.isBusy )
{
wait ... *without* releasing control
}
now,on csq,do BBB then proceed
print ( "****" )
print ( "Main will now wait for csq to finish what it is doing ..." )
print ( "But note," )
print ( "it *blocks* until csq is finished. So it deadlocks." )
}
这也会阻止,即使我只向 CSQ 提交了一个块。
要打破僵局,您可以例如当您等待释放控制(在这种情况下,您可以调用 async 而不是 sync)或使用不同类型的锁或以不同方式等待另一个完成时。
编辑 2
让我还原它的本质。
// This runs on main
// This runs on csq
csq.async { main.sync // csq now waits on main to free up }
csq.sync // main now waits on csq to free up
// and you have deadlock
,
为了扩展 Tushar Sharma 和 Dipak 的回答,我将按照代码的执行顺序逐步介绍该代码。
// == scheduling a work item from the main queue ==
// Create a new serial queue
let customserialQueue = DispatchQueue(label: "com.test.dipak")
// Create a work item and append it to customserialQueue.
// Don't think of this being "in parallel." these are not threads. They're
// queues. It will run the next time customserialQueue is scheduled. That might
// be immediately (if there's an available corE),and that might be in the
// arbitrarily distant future. It doesn't matter what's in this work item. It's
// just "some work to do."
customserialQueue.async { ... }
// On main queue still
print("Step 4")
// Create a work item,append it to customserialQueue,and wait for it to
// complete. As before,it doesn't matter what's in this work item. It's just
// stuck onto the end of customserialQueue and will execute when it gets to the
// front of the queue and the queue is scheduled. Currently it's 2nd in line
// after the Step 2 work item.
customserialQueue.sync { ... }
此时,main 必须让步(block)。它无法前进并完成 当前工作项(运行 serialQueueTest 的工作项),直到第 5 步工作项完成。
由于现在什么都没有运行,customserialQueue 上的第一个块可以运行。
// == scheduling a work item from customserialQueue ==
print("Step 2")
// Create a block,append it the main queue,and wait for it to complete.
DispatchQueue.main.sync { ... }
和以前一样,customserialQueue 必须让出(阻塞)。在第 3 步工作项完成之前,它无法继续并完成当前工作项(运行第 2 步的工作项)。并且在 main 完成当前正在运行的工作项之前无法安排第 3 步工作项(main 是一个串行队列)。
此时main被阻塞等待“Step 5”阻塞完成,customserialQueue阻塞等待“Step 3”完成。这是一个经典的僵局,两个任务都无法进行。
在存在多核的情况下,上述任何变化都没有。 GCD 队列是关于并发性的,而不是并行性(和 concurrency is not parallelism)。它们不是关于“同时”运行的东西。它们是关于安排工作项目的。所以你应该首先对它们进行推理,就好像它们在单个内核上运行一样。然后,您可以添加关于如果两个工作项同时运行会发生什么的问题。但是这个问题并没有改变依赖的基本问题。
以上是大佬教程为你收集整理的为什么两个不同的串行队列会在 swift 中造成死锁?全部内容,希望文章能够帮你解决为什么两个不同的串行队列会在 swift 中造成死锁?所遇到的程序开发问题。
如果觉得大佬教程网站内容还不错,欢迎将大佬教程推荐给程序员好友。
本图文内容来源于网友网络收集整理提供,作为学习参考使用,版权属于原作者。
如您有任何意见或建议可联系处理。小编QQ:384754419,请注明来意。