我的主要目标是能够拥有一些其他线程在完成之前不应该访问的同步方法。 如果我有通常的VM - 我会将此方法标记为已同步。 但是在GAE中我有多个实例。 我读到的关于此的所有帖子都说我应该使用memcache或数据存储区。 但到底是怎么回事?
答案 0 :(得分:6)
通常答案是重新设计功能,因此不需要全局同步。即使你设法同步它,它也只是一个瓶颈。
你可能最好在后端实现它;您可以指定单个后端,并使您的函数调用对后端的请求。您也可以使用memcache或数据存储区作为信号量,但所有这些都会给您带来糟糕的性能。
答案 1 :(得分: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));
}