4

我的主要目标是能够拥有一些在完成之前不应被其他线程访问的同步方法。如果我有通常的 VM - 我会将此方法标记为同步。但在 GAE 中,我有多个实例。我读到的所有帖子都说我应该使用 memcache 或数据存储。但究竟如何?

4

2 回答 2

6

通常答案是重新设计函数,因此它不需要全局同步。即使您设法同步它,它也是一个瓶颈。

您可能最好在后端实现它;您可以指定一个后端,并使您的函数调用后端的请求。您也可以使用 memcache 或数据存储作为信号量,但所有这些都会给您带来较差的性能。

于 2013-02-16T08:23:13.033 回答
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));
}
于 2013-02-16T15:20:18.123 回答