javascript - JavaScript 中的互斥量——这看起来像是一个正确的实现吗?

标签 javascript mutex

这不是一个完全严肃的问题,更像是一个淋浴的想法:JavaScript 的 await 关键字应该允许一些感觉非常像普通“并发语言”中的互斥体的东西。

function Mutex() {
    var self = this; // still unsure about how "this" is captured
    var mtx = new Promise(t => t()); // fulfilled promise ≡ unlocked mutex
    this.lock = async function() {
        await mtx;
        mtx = new Promise(t => {
            self.unlock = () => t();
        });
    }
}
// Lock
await mutex.lock();
// Unlock
mutex.unlock();

这是正确的实现吗(除了正确的错误处理)?而且……我可以使用 C++-RAII 风格的锁守卫吗?

最佳答案

您的实现允许尽可能多的消费者获得锁;每次调用 lock 都会等待一个 promise :

function Mutex() {
    var self = this; // still unsure about how "this" is captured
    var mtx = new Promise(t => t()); // fulfilled promise ≡ unlocked mutex
    this.lock = async function() {
        await mtx;
        mtx = new Promise(t => {
            self.unlock = () => t();
        });
    }
}

const mutex = new Mutex();

(async () => {
  await Promise.resolve();
  await mutex.lock();
  console.log("A got the lock");
})();
(async () => {
  await Promise.resolve();
  await mutex.lock();
  console.log("B got the lock");
})();

您需要实现一个 promise 队列,为每个锁定请求创建一个新 promise 。

旁注:

  • new Promise(t => t()) 可以写得更简单和地道 Promise.resolve() :-)
  • 如果您正在使用这样的箭头函数,则不需要 self;箭头函数关闭创建它们的this(就像关闭变量一样)
  • unlock 可能是锁 promise 的解析值,因此只有获得锁的代码才能释放它

像这样:

function Mutex() {
    let current = Promise.resolve();
    this.lock = () => {
        let _resolve;
        const p = new Promise(resolve => {
            _resolve = () => resolve();
        });
        // Caller gets a promise that resolves when the current outstanding
        // lock resolves
        const rv = current.then(() => _resolve);
        // Don't allow the next request until the new promise is done
        current = p;
        // Return the new promise
        return rv;
    };
}

实例:

"use strict";
function Mutex() {
    let current = Promise.resolve();
    this.lock = () => {
        let _resolve;
        const p = new Promise(resolve => {
            _resolve = () => resolve();
        });
        // Caller gets a promise that resolves when the current outstanding
        // lock resolves
        const rv = current.then(() => _resolve);
        // Don't allow the next request until the new promise is done
        current = p;
        // Return the new promise
        return rv;
    };
}

const rand = max => Math.floor(Math.random() * max);

const delay = (ms, value) => new Promise(resolve => setTimeout(resolve, ms, value));

const mutex = new Mutex();

function go(name) {
    (async () => {
        console.log(name + " random initial delay");
        await delay(rand(50));
        console.log(name + " requesting lock");
        const unlock = await mutex.lock();
        console.log(name + " got lock");
        await delay(rand(1000));
        console.log(name + " releasing lock");
        unlock();
    })();
}
go("A");
go("B");
go("C");
go("D");
.as-console-wrapper {
  max-height: 100% !important;
}

关于javascript - JavaScript 中的互斥量——这看起来像是一个正确的实现吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/51086688/

相关文章:

javascript - fancybox2 的问题 - $.fancybox.resize 不是函数 - 错误

javascript - 如何使用 JavaScript 检查鼠标是向上还是向下移动?

javascript - ReactDOM 未定义(但来自 React 方法)

javascript - 单击动态创建的按钮时如何暂停嵌入式 mp4 的播放?

c++ - 如何减少使用std::condition_variable时生产者获得锁而消费者无法获得锁的可能性?

c++ - 没有全局互斥锁的 pThread 互斥锁

multithreading - 对与 unique_lock 关联的互斥体调用解锁会导致未定义的行为

c++ - 将互斥保护构建到 C++ 类中的线程安全方法?

c++ - 使用 C++ 在多个互斥体上调用 WaitForMultipleObjects 并设置超时

Javascript:计算转换为UTC的2天之间的时差