在Swift中,我们可以利用DispatchQueue
来防止竞争状况。通过使用串行队列,所有内容都按顺序执行,从https://developer.apple.com/library/content/documentation/General/Conceptual/ConcurrencyProgrammingGuide/OperationQueues/OperationQueues.html
串行队列(也称为私有调度队列)执行一项任务 按照它们添加到队列的顺序。该 当前执行的任务在不同的线程上运行(可能会有所不同) 从任务到任务)由调度队列管理。串行 队列通常用于同步对特定资源的访问。
但我们可以通过在sync
内执行async
轻松创建死锁How do I create a deadlock in Grand Central Dispatch?
let serialQueue = DispatchQueue(label: "Cache.Storage.SerialQueue")
serialQueue.async {
serialQueue.sync {
print("perform some job")
}
print("this can't be reached")
}
防止死锁的唯一方法是使用2个串行队列,每个队列用于sync
和async
个功能版本。但是,当writeSync
和writeAsync
同时发生时,这可能会导致罕见的情况。
我在fs module中看到它支持sync
和async
功能,例如fs.writeFileSync(file, data[, options])
和fs.writeFile(file, data[, options], callback)
。通过允许这两个版本,这意味着用户可以按照他们想要的任何顺序使用它们吗?那么他们可以轻松地创建像我们上面所做的那样的死锁?
所以也许fs
有一种聪明的方式可以应用于Swift?我们如何以线程安全的方式支持sync
和async
?
答案 0 :(得分:1)
serialQueue.async {
serialQueue.sync {
print("perform some job")
}
}
此死锁是因为此代码在同一个调度队列上排队第二个任务,然后等待第二个任务完成。然而,第二个任务甚至无法启动,因为它是一个串行队列,并且第一个任务仍在执行(虽然在内部sempahore上被阻止)。
避免这种僵局的方法是从不这样做。当你认为你可以通过以下方式达到同样的效果时,这是特别愚蠢的:
serialQueue.async {
print("perform some job")
}
有一些用例可以将不同队列中的同步任务运行到您所在的队列中。
但是,在同一个队列中同步执行某些操作永远不会有理由,您可能只需执行某些操作。换句话说,如果您只是一个接一个地编写语句,它们已经在同一队列上同步执行。
我在fs模块中看到它支持同步和异步功能,如fs.writeFileSync(文件,数据[,选项])和fs.writeFile(文件,数据[,选项],回调)。通过允许这两个版本,这意味着用户可以按照他们想要的任何顺序使用它们吗?那么他们可以轻松地创建像我们上面所做的那样的死锁?
这取决于两个API的实现方式。调用的同步版本可能只是在不弄乱其他线程的情况下进行调用。如果它确实抓住了另一个线程然后等待其他线程完成,那么如果node.js
服务器的线程用尽,则可能会出现死锁。