3

LockService のドキュメント: https://developers.google.com/apps-script/service_lockには、「getPublicLock() -現在のユーザーの同時実行による コードのセクションへの同時アクセスを防止するロックを取得する」と記載されています。

したがって、クエリはコメントの周りにあります: " section of code "。LockService.getPublicLock() を使用するコードのセクションが複数ある場合、それらは本質的に独立したロックですか?

例えば:

function test1() {
    var lock = LockService.getPublicLock();

    if (lock.tryLock(10000)) {
        // Do some critical stuff
        lock.releaseLock();
    }
}


function test2() {
    var lock = LockService.getPublicLock();

    if (lock.tryLock(10000)) {
        // Do some critical stuff
        lock.releaseLock();
    }
}

1 人のユーザーが test1() にアクセスし、別のユーザーが test2() にアクセスして、スクリプトの 2 つの呼び出しを同時に実行した場合、両方とも成功しますか? または、この投稿で言及されているように: http://googleappsdeveloper.blogspot.co.uk/2011/10/concurrency-and-google-apps-script.htmlロックは単にスクリプト レベルで行われているのでしょうか? したがって、このシナリオでは、test1() または test2() のいずれかのみが成功し、両方は成功しません。

ドキュメントに記載されているとおりであり、両方が成功する場合、「コードのセクション」とは何を意味しますか?? LockService.getPublicLock() が表示されるのは行番号ですか、それとも周囲の関数ですか?

4

2 に答える 2

3

公開鍵は 1 つだけ、私有鍵は 1 つだけです。

複数のロックが必要な場合は、ある種の名前付きロック サービスを自分で実装する必要があります。以下の例では、スクリプト データベース機能を使用しています。

var validTime = 60*1000;  // maximum number of milliseconds for which a lock may be held
var lockType = "Named Locks";  // just a type in the database to identify these entries
function getNamedLock( name ) {
  return {
    locked: false,
    db : ScriptDb.getMyDb(),
    key: {type: lockType, name:name },
    lock: function( timeout ) {
      if ( this.locked ) return true;
      if ( timeout===undefined ) timeout = 10000;
      var endTime = Date.now()+timeout;
      while ( (this.key.time=Date.now()) < endTime ) {
        this.key = this.db.save( this.key );
        if ( this.db.query( 
              {type: lockType, 
               name:this.key.name, 
               time:this.db.between( this.key.time-validTime, this.key.time+1 ) }
            ).getSize()==1 )
          return this.locked = true;        // no other or earlier key in the last valid time, so we have it
        db.remove( this.key );              // someone else has, or might be trying to get, this lock, so try again
        Utilities.sleep(Math.random()*200); // sleep randomly to avoid another collision
      }
      return false;
    },
    unlock: function () {
      if (this.locked) this.db.remove(this.key);
      this.locked = false;
    }
  }
}

このサービスを使用するには、次のようにします。

var l = getNamedLock( someObject );
if ( l.lock() ) {
  // critical code, can use some fields of l for convenience, such as
  // l.db - the database object
  // l.key.time - the time at which the lock was acquired
  // l.key.getId() - database ID of the lock, could be a convenient unique ID
} else {
  // recover somehow
}
l.unlock();

ノート:

  1. これは、データベース操作 db.save() が本質的に分割できないことを前提としています-そうでなければ、通常の使用で大きな問題が発生するため、分割できないと思います。

  2. 時間はミリ秒単位であるため、複数のタスクが同じタイムスタンプでロックを試みる可能性があると想定する必要があります。そうでない場合、関数は単純化されます。

  3. いずれにせよ実行時間制限によりスクリプトが停止するため、ロックが 1 分以上保持されることはないと想定しています (ただし、これは変更できます)。

  4. データベースがクラッシュしたスクリプトによる古いロックで混乱するのを防ぐために、データベースから 1 分以上経過したすべてのロックを定期的に削除する必要があります。

于 2013-10-02T13:04:10.603 に答える