1
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

JavascriptでMonitor(同期)

Last updated at Posted at 2020-04-12

Monitorクラス

稀ではあるが、JavascriptでCtirical Section的なものを導入したくなる時がある。
同期方法の一種であるMonitor を実現するMonitorクラスを作ってみた。

function Monitor(){
    this.promises = [];
    this.resolvers = [];
}

Monitor.prototype.enter = function(){
    this.promises.push(new Promise((res,rej)=>{ this.resolvers.push(res); })); // This promise is for the next waiter
    return this.promises.length == 1 ? Promise.resolve(true) : this.promises[this.promises.length-2];
};

Monitor.prototype.exit = function(){
    if(this.promises.length<=0) return; // Invalid use of exit
    this.resolvers[0](true); // Invoke the first waiter
    this.promises.shift();
    this.resolvers.shift();
};

使い方

atomicにしたい処置をawait monitor.enter(), monitor.exit()で囲む。await monitor.enter()は他にCritical Sectionに入っている処理がある場合、それが終わるまでブロックする。Javascriptはシングルスレッドなのでatomicに処理したい部分の少なくとも一箇所は、非同期に実行している一連のコード(thenチェーン)になるでしょう。

money=10000円に対して1000円減らして2000円足す、という処理が何らかの理由で非同期で実行されていてかつ不可分に実施する必要がある場合(つまり、money=9000円の状態で参照されてはならない).

// Monitor object
var monitor = new Monitor();

//....

// Part A
await monitor.enter();
var money = 10000; 
doSomething()
.then(()=>{
  money -= 1000;
})
.then(()=>{
  money += 2000;
})
.finally(()=>{
  monitor.exit();
});

// .... 別の場所 ....
// Part B

await monitor.enter();
if(money >= 10000)
   console.log("お金足りるよ");
else
   console.log("お金足りないよ");
monitor.exit();

1
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?