我正在使用spymemcached客户端来实现我的缓存逻辑。不知何故,我需要使用CAS同时修改缓存中的某些内容。
我看到所有者已经在这里展示了如何使用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”怎么办?有什么潜在的问题?
[UPDATE]
我正在关注示例代码并实现了这样的方法,这会起作用吗?
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);
}
我最担心的是它是否是线程安全的。
答案 0 :(得分:2)
如果没有使用该库,我相信如果您没有复制会发生什么,在这种特殊情况下,当您尝试修改时会出现异常{{1这是不可变的。 Collections.singletonList()
的某些实现根本无法修改,假设您可以这样做通常是个坏主意。 (如果Java将List
的概念分离为索引可读序列,并将List
子接口与所有MutableList
和add
操作分开,那就太好了,但是哦孔)。
从广义上讲,我甚至不确定它“不是绝对必要的”。这里发生的事情是,您将获得现有的项目列表,并被要求返回一个新值,以便在CAS条件成立时使用。如果您修改了列表然后返回set
,则问题是您失去了条件 - 当前列表已已被修改(由您),即使CAS逻辑意味着你提出的新价值被拒绝了。
现在也许这在实践中并不重要,因为库逻辑意味着实际存储在缓存中的值不会更新;并且更改瞬态也不是问题,因为经过足够的尝试后,您的更新将会成功。
但是,尽管如此,我同意没有理由不使用功能方法 - 您将获得一个输入参数来读取,并且应该返回一个包含您的列表的列表修改。对于程序的清晰度,健壮性和推理,创建一个具有正确值的新列表并返回该列表要好得多。否则可能会或可能不会起作用,但是当您可以选择明确地编写某些内容时,谁想要编写其语义依赖于其他库的实现细节的代码?