3

在 LockService 文档中:https ://developers.google.com/apps-script/service_lock它声明“getPublicLock() - 获取一个锁,通过当前用户的同时执行来 防止同时访问一段代码”

因此查询围绕注释:“代码段”。如果我有多个使用 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();
    }
}

如果我有两个脚本调用同时执行,一个用户访问 test1(),另一个用户访问 test2(),他们都会成功吗?或者正如它在这篇文章中所暗示的那样:http: //googleappsdeveloper.blogspot.co.uk/2011/10/concurrency-and-google-apps-script.html只是脚本级别的锁吗?因此,对于这种情况,只有 test1() 或 test2() 之一会成功,但不会同时成功。

如果确实如文档所述,并且两者都会成功,那么什么表示“代码段”?是 LockService.getPublicLock() 出现的行号还是周围的函数?

4

2 回答 2

3

公用锁只有一把,私用锁只有一把。

如果您希望拥有多个锁,您需要自己实现某种命名锁服务。下面的示例,使用脚本数据库功能:

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. 我们假设锁的持有时间永远不会超过一分钟(但您可以更改它),因为执行时间限制无论如何都会停止您的脚本。

  4. 您应该定期从数据库中删除超过一分钟的所有锁,以防止它被崩溃脚本中的旧锁弄乱。

于 2013-10-02T13:04:10.603 回答
2

这个问题太老了,现在“getPublicLock()”不再可用。

根据https://developers.google.com/apps-script/reference/lock 此时 LockServise 呈现这三个范围:

getDocumentLock():获取一个锁,以防止当前文档的任何用户同时运行一段代码。

getScriptLock():获取一个锁,以防止任何用户同时运行一段代码。

getUserLock():获取一个锁,防止当前用户同时运行一段代码。

于 2020-09-10T22:50:26.447 回答