NodeJS:从多个承诺中读取和写入共享对象
NodeJS: Reading and writing to a shared object from multiple promises
我正在尝试找出从多个承诺访问对象时是否会出现问题,例如:
let obj = {test: 0}
let promisesArr = []
for (let n = 0; n < 10; n++) {
promisesArr.push(promiseFunc(obj))
}
Promise.all(promisesArr)
// Then the promise would be something like this
function promiseFunc(obj) {
return new Promise(async (resolve, reject) => {
// read from the shared object
let read = obj.test
// write/modify the shared object
obj.test++
// Do some async op with the read data
await asyncFunc(read)
// resolves and gets called again later
})
}
据我所知see/tested不会有问题,看起来即使处理是异步的,也不存在竞争条件。但也许我可能会遗漏一些东西。
我能看到的唯一问题是写入对象然后执行一些 I/O 操作然后读取期望之前写入的内容仍然存在
我不是在一开始就在其他异步操作之后修改对象,但是有几个承诺在做同样的事情。一旦他们解决了,他们就会再次被召唤,然后循环重新开始。
Javascript 中具有多个异步操作的竞争条件完全取决于您所做的应用程序逻辑。
由于您没有在这方面显示任何真实代码,因此我们无法确定您是否有竞态条件责任。
您的问题没有通用答案。
是的,访问相同数据的多个异步操作之间可能存在竞争条件。
或
可以适当地编写代码,这样就不会出现竞争条件。
这完全取决于准确和真实的代码及其作用。没有通用的答案。我可以向您展示包含两个绝对会导致竞争条件的基于承诺的异步操作的代码,也可以向您展示包含两个不会导致竞争条件的基于承诺的异步操作的代码。 因此,对竞争条件的敏感性取决于精确的代码、它在做什么以及它是如何编写的。
对共享对象中值的纯粹简单访问本身不会导致竞争条件,因为 Javascript 中的主线程是单线程且不可中断的,因此任何单个同步 Javascript语句本身是线程安全的。重要的是你如何处理这些数据以及如何编写代码。
如果有其他操作也可以更改,下面是一个容易受到竞争条件影响的示例 shareObj.someProperty
:
let localValue = shareObj.someProperty;
let data = await doSomeAsyncOperation();
shareObj.someProperty = localValue + data.someProperty;
然而,这不会导致竞争条件:
let data = await doSomeAsyncOperation();
shareObj.someProperty = shareObj.someProperty += data.someProperty;
第二个不会导致自己的竞争条件,因为它正在自动更新共享数据。而第一个是获取它,将其存储在本地,然后等待异步操作完成,这是其他代码修改共享变量而本地函数不知道的机会。
仅供参考,这与经典数据库问题非常相似。如果您从数据库中获取一个值(这在 nodejs 中始终是一个异步操作),然后递增它,然后写回该值,这会受到竞争条件的影响,因为其他人可能会同时尝试 read/modify 该值时间,你可以践踏彼此的变化。因此,您必须使用数据库中内置的原子操作在一个原子操作中更新变量。
对于Javascript中你自己的变量,这个问题比一般的数据库问题稍微简单一点,因为读取和写入Javascript变量是原子的。您只需确保您不持有稍后将在异步操作中修改和写回的值。
我正在尝试找出从多个承诺访问对象时是否会出现问题,例如:
let obj = {test: 0}
let promisesArr = []
for (let n = 0; n < 10; n++) {
promisesArr.push(promiseFunc(obj))
}
Promise.all(promisesArr)
// Then the promise would be something like this
function promiseFunc(obj) {
return new Promise(async (resolve, reject) => {
// read from the shared object
let read = obj.test
// write/modify the shared object
obj.test++
// Do some async op with the read data
await asyncFunc(read)
// resolves and gets called again later
})
}
据我所知see/tested不会有问题,看起来即使处理是异步的,也不存在竞争条件。但也许我可能会遗漏一些东西。
我能看到的唯一问题是写入对象然后执行一些 I/O 操作然后读取期望之前写入的内容仍然存在
我不是在一开始就在其他异步操作之后修改对象,但是有几个承诺在做同样的事情。一旦他们解决了,他们就会再次被召唤,然后循环重新开始。
Javascript 中具有多个异步操作的竞争条件完全取决于您所做的应用程序逻辑。
由于您没有在这方面显示任何真实代码,因此我们无法确定您是否有竞态条件责任。
您的问题没有通用答案。
是的,访问相同数据的多个异步操作之间可能存在竞争条件。
或
可以适当地编写代码,这样就不会出现竞争条件。
这完全取决于准确和真实的代码及其作用。没有通用的答案。我可以向您展示包含两个绝对会导致竞争条件的基于承诺的异步操作的代码,也可以向您展示包含两个不会导致竞争条件的基于承诺的异步操作的代码。 因此,对竞争条件的敏感性取决于精确的代码、它在做什么以及它是如何编写的。
对共享对象中值的纯粹简单访问本身不会导致竞争条件,因为 Javascript 中的主线程是单线程且不可中断的,因此任何单个同步 Javascript语句本身是线程安全的。重要的是你如何处理这些数据以及如何编写代码。
如果有其他操作也可以更改,下面是一个容易受到竞争条件影响的示例 shareObj.someProperty
:
let localValue = shareObj.someProperty;
let data = await doSomeAsyncOperation();
shareObj.someProperty = localValue + data.someProperty;
然而,这不会导致竞争条件:
let data = await doSomeAsyncOperation();
shareObj.someProperty = shareObj.someProperty += data.someProperty;
第二个不会导致自己的竞争条件,因为它正在自动更新共享数据。而第一个是获取它,将其存储在本地,然后等待异步操作完成,这是其他代码修改共享变量而本地函数不知道的机会。
仅供参考,这与经典数据库问题非常相似。如果您从数据库中获取一个值(这在 nodejs 中始终是一个异步操作),然后递增它,然后写回该值,这会受到竞争条件的影响,因为其他人可能会同时尝试 read/modify 该值时间,你可以践踏彼此的变化。因此,您必须使用数据库中内置的原子操作在一个原子操作中更新变量。
对于Javascript中你自己的变量,这个问题比一般的数据库问题稍微简单一点,因为读取和写入Javascript变量是原子的。您只需确保您不持有稍后将在异步操作中修改和写回的值。