LockService含糊不清 [英] LockService ambiguity

查看:149
本文介绍了LockService含糊不清的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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



所以查询是在代码部分评论附近。如果我有使用LockService.getPublicLock()的多段代码,它们实质上是独立的锁吗?



例如:

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

if(lock.tryLock(10000)){
//做一些关键的事情
lock.releaseLock();




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

if(lock.tryLock(10000)){
//做一些关键的事情
lock.releaseLock();






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



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

解决方案

只有一个公共锁和一个私人锁。

<如果你想有几个锁,你需要自己实现某种指定的锁服务。以下示例使用脚本数据库功能:

  var validTime = 60 * 1000; //可以保持锁定的最大毫秒数
var lockType =命名锁定; //只是数据库中的一个类型来标识这些条目
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; ((this.key.time = Date.now())< endTime){
this.key = this.db.save(this.key);
while(
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; //在上次有效时间内没有其他或更早的键,所以我们有
db.remove(this.key); //其他人拥有或可能试图获得此锁,因此请重试
Utilities.sleep(Math.random()* 200); //随机休眠以避免另一次碰撞
}
return false;
},
unlock:function(){
if(this.locked)this.db.remove(this.key);
this.locked = false;
}
}
}

要使用这项服务,我们'd做类似的事情:

  var l = getNamedLock(someObject); 
if(l.lock()){
//关键代码,为了方便可以使用l的某些字段,如
// l.db - 数据库对象
// l.key.time - 获取锁的时间
// l.key.getId() - 锁的数据库ID,可能是一个方便的唯一ID
} else {
//以某种方式恢复
}
l.unlock();

注意:


    假设数据库操作db.save()基本上是不可分的 - 我认为它是必须的,否则在正常使用中会遇到BIG麻烦。
  1. 因为时间以毫秒为单位,所以我们必须假设有多个任务可以使用相同的时间戳尝试锁定,否则可以简化该功能。


  2. 我们假设锁永远不会持续超过一分钟(但您可以更改它),因为执行时间限制无论如何都会停止脚本。


  3. 定期您应该从数据库中删除所有超过一分钟的锁,以保存它与崩溃脚本中的旧锁混乱。



In the LockService documentation: https://developers.google.com/apps-script/service_lock it states that "getPublicLock() - Gets a lock that prevents concurrent access to a section of code by simultaneous executions for the current user"

So the query is around the comment: "section of code". If I have multiple sections of code that use the LockService.getPublicLock(), are they essentially independent locks?

For example:

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();
    }
}

If I have two invocations of my script concurrently executing, with one user accessing test1() and another user accessing test2(), will they both succeed? Or as it alludes to in this post: http://googleappsdeveloper.blogspot.co.uk/2011/10/concurrency-and-google-apps-script.html are the locks simply at the script level? So for this scenario, only one of test1() or test2() would succeed but not both.

If it is truly as the documentation states, and both will succeed, what denotes a 'section of code' ?? Is it the line numbers that the LockService.getPublicLock() appears on or is it the surrounding function?

解决方案

There is only one public lock and only one private lock.

If you wish to have several locks you'll need to implement some sort of named lock service yourself. An example below, using the script database functionality:

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;
    }
  }
}

To use this service, we'd do something like:

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();

Notes:

  1. This assumes that the database operation db.save() is essentially indivisible - I think it must be, because otherwise there would be BIG trouble in normal use.

  2. Because the time is in milliseconds we have to assume that it is possible for more than one task to try the lock with the same time stamp, otherwise the function could be simplified.

  3. We assume that locks are never held for more than a minute (but you can change this) since the execution time limit will stop your script anyway.

  4. Periodically you should remove all locks from the database that are more than a minute old, to save it getting cluttered with old locks from crashed scripts.

这篇关于LockService含糊不清的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆