2013-02-16 66 views

回答

6

通常情況下,答案是重新設計的功能,所以它不需要全局同步。即使你設法同步它,它也是一個瓶頸。

你可能最好在後端實現它;你可以指定一個後端,並讓你的函數調用對後端的請求。您也可以使用memcache或數據存儲作爲信號量,但所有這些都會給您帶來糟糕的性能。

+0

**您也可以使用memcache或數據存儲作爲信號量**究竟如何? – Boris 2013-02-16 12:59:41

+0

請不要建議我不要有synronized動作。這是非常常見的情況,並且在通常的應用中可以完美運行。 – Boris 2013-02-16 13:01:45

+0

邏輯上你知道如何實現信號量。如果採用這種方式,您可能希望將CAS與memcache結合使用。 https://developers.google.com/appengine/docs/python/memcache/overview#Using_Compare_and_Set_in_Python – 2013-02-16 13:32:41

1

其實我並沒有使用那種同步。 一旦我做到了。它似乎工作得很好。 下面是一個例子

String syncKey = "Sync:" + req.getRequestURI(); 
boolean lockAcquired = false; 
try { 
    lockAcquired = acquireLock(syncKey, 5000L); 
    if (!lockAcquired) { 
    return; 
    } 
    // do something here 

} finally { 
    if (lockAcquired) { 
    memcacheService.delete(syncKey); 
    } 
} 


public boolean acquireLock(String syncKey, long maxwait) { 
    long start = System.currentTimeMillis(); 
    while (true) { 
    if (memcacheService.increment(syncKey, 1L, 0L) == 1L) { 
     return true; 
    } 
    if (System.currentTimeMillis() - start > maxwait) { 
     return false; 
    } 
    try { 
     Thread.sleep(100L); 
    } catch (InterruptedException e) { 
    } 
    } 
} 

一般我使用更簡單的同步。它讓我有機會只運行一段代碼。

final long now = System.currentTimeMillis()/(60L * 1000L); // expire every minute 
if (memcacheService.increment("VoteRemoveOldTask" + now, 1L, 1L) == 1L) { 
    QueueFactory.getDefaultQueue().add(
     TaskOptions.Builder.withDefaults().url(VoteRemoveOldTask.URL)); 
} 
+1

有關無法依賴memcache的原因,請參閱https://cloud.google.com/developers/articles/best-practices-for-app-engine-memcache。 – ErstwhileIII 2014-02-12 04:36:48

+0

同意。但同時對於簡單的情況也是如此。 – 2016-11-18 16:33:20

相關問題