2013-02-16 68 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

相关问题