2013-02-26 96 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