【发布时间】:2023-04-09 09:14:01
【问题描述】:
我有这种情况:
const q1 = async.queue((task,cb) => task(cb), 1);
const q2 = async.queue((task,cb) => task(cb), 3);
基本上,情况是 - 如果我可以锁定 q1,我可以在 q2 中同时处理多达 3 件事情。 Aka,我程序中的大多数东西都必须串行运行,但当然可以并行运行,但前提是它们首先在 q1 上获得“锁”。然而,事实证明,写这篇文章比预期的要难得多。我认为这类似于读/写锁定问题。 https://en.wikipedia.org/wiki/Readers%E2%80%93writer_lock
换句话说,如果我锁定了 q1,我只能处理 q2 中的事情。实现这一点的一个问题是,如果我总是必须在 q2 的关键部分获取 q1 上的锁,那么我将无法在 q2 中使用更高的并发级别,它将始终是串行的。
我现在唯一的想法是翻转一个布尔值,如下所示:
let q2HasLock = false;
if(q2hasLock === true){
q2.push(cb => ...);
}
else{
q1.push(cb => ...);
}
那么我可以使用这个:
q2.drain = () => {
q2HasLock = false;
};
但剩下的部分是我不知道如何/何时将q2HasLock 翻转为true。希望您了解问题/想法。这个实现的另一个问题是,推送到 q2 的请求可能会饿死发送到 q1 的请求,所以我可以这样做:
let q2HasLock = false, count = 0 ;
if(q2hasLock === true && count < 3){
count++;
q2.push(cb => ...);
}
else{
q1.push(cb => ...);
}
q2.drain = () => {
count = 0;
q2HasLock = false;
};
这有点麻烦 - 我想尽可能简单地实现它!
【问题讨论】:
-
能否请您详细说明队列将执行什么样的任务?你可能知道,JS 是单线程的,除了委托给
libuv的 theadpool 的任何异步操作,如文件或网络 I/O,默认设置为 4。这意味着 Node 无法运行并行执行超过 4 个异步操作,除非您更改UV_THREADPOOL_SIZE环境变量。在单线程环境中不需要像 Mutexes(这就是这个锁)这样的同步原语。 -
大部分队列任务都会做异步 I/O,是的
标签: javascript node.js concurrency queue async.js