2013-02-26 98 views
2

在的LockService文档:https://developers.google.com/apps-script/service_lock它指出“getPublicLock() - 获取一个锁,用于防止对通过同时执行当前用户一个部的代码并发访问”的LockService歧义

所以查询是围绕评论:“部分代码”。如果我有使用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()出现的行号还是周围的函数?

回答

2

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

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

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()基本上是不可分割的 - 我认为它一定是,因为否则在正常使用中会出现BIG麻烦。

  2. 由于时间以毫秒为单位,因此我们必须假设多个任务可能尝试使用相同时间戳的锁定,否则可能会简化该功能。

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

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

+0

这个答案/场景仍然准确吗?我试图确定一个单独的锁实例是否可以在单独的函数中使用('.getPublicLock()'似乎不再存在,但是'getScriptLock()')。所以'var lock_01 = LockService.getScriptLock();'可以在'function_01()'中使用,'var lock_02 = LockService.getScriptLock();'可以在'function_02()'中使用吗? – user1063287 2017-07-19 04:30:56