2012-04-24 67 views
0

我使用spymemcached客户端来实现我的缓存逻辑的示例代码。不知何故,我需要使用CAS来同时修改缓存中的某些内容。不明白spymemcached

只见主人已经显示了如何从这里使用CASMutation一个很好的例子:http://code.google.com/p/spymemcached/wiki/Examples#Using_CAS

但我对代码的这一部分一个问题:

// Not strictly necessary if you specify the storage as 
// LinkedList (our initial value isn't), but I like to keep 
// things functional anyway, so I'm going to copy this list 
// first. 
LinkedList<Item> ll = new LinkedList<Item>(current); 

即使我仔细阅读评论,我仍然不明白它在这里试图做什么。如果我们只是使用“当前”而没有复制到“ll”会怎么样?潜在的问题是什么?

[更新]

我下面的示例代码和实现的方法是这样,将这项工作?

public <T> Set<T> addItemToSet(String key, int expire, final T newItem) throws Exception  { 

    // This is how we modify a list when we find one in the cache. 
    CASMutation<Set<T>> mutation = new CASMutation<Set<T>>() { 

     // This is only invoked when a value actually exists. 
     public Set<T> getNewValue(Set<T> current) { 
      current.add(newItem); 
      return current; 
     } 

    }; 

    HashSet<T> initialValue= new HashSet<T>(); 
    initialValue.add(newItem); 

    CASMutator<Set<T>> mutator = new CASMutator<Set<T>>(memClient, getTranscoder()); 

    return mutator.cas(key, initialValue, expire, mutation); 
} 

我主要关心它是否是线程安全的。

回答

2

,而无需使用图书馆,我相信如果你不复制,在这种特殊的情况下会发生什么,就是当你试图修改Collections.singletonList(),这是不可改变的,你会得到一个异常。的List某些实现根本不能被修改,并且它通常是一个坏主意,认为你可以。 (如果Java将List的概念作为索引可读序列和MutableList子接口与所有addset操作分开,但是很好)。

在更广泛的意义上,我甚至不能肯定这是“不是绝对必要的”。这里发生的事情是,您将得到现有的项目列表,并要求返回一个新的值,以便在CAS条件成立时使用。如果修改到位名单,然后返回current,问题是,你已经失去了条件 - 当前列表中被修改(由你),即使CAS逻辑意味着你提出的新的价值被拒绝。

现在可能这实际上并不重要,因为库逻辑意味着实际存储在缓存中的值不会更新;并且改变瞬时状态也不是问题,因为经过足够的尝试后,您的更新将成功。

尽管如此,我同意没有任何理由不使用函数式方法 - 您将得到一个输入参数来读取,并且预计会返回一个包含您的修改的列表。对于程序的清晰性,健壮性和推理来说,用正确的值创建一个新列表并返回它会更好。否则可能会或可能无法工作,但是谁愿意编写其语义取决于其他库的实现细节的代码,何时可以选择写出明确的内容?