0

我正在使用 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);

即使我仔细阅读了评论,我仍然不明白它在这里试图做什么。如果我们只使用“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);
}

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

4

1 回答 1

2

在没有使用该库的情况下,我相信如果您不复制会发生什么,在这种特殊情况下,您会在尝试修改时遇到异常Collections.singletonList(),这是不可变的。某些实现List根本无法修改,假设您可以修改通常是个坏主意。(如果 Java 将 a 的概念分离List为索引可读序列和MutableList具有所有addandset操作的子接口,那就太好了,但是哦)。

从更广泛的意义上说,我什至不确定它“不是绝对必要的”。这里发生的情况是,您将获得现有的项目列表,并被要求返回一个新值以在 CAS 条件成立时使用。如果您修改列表然后返回current,问题是您失去了条件 - 当前列表被修改(由您),即使 CAS 逻辑意味着您提出的新值被拒绝。

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

但尽管如此,我同意完全没有理由不使用函数式方法——你被赋予了一个read的输入参数,并且应该返回一个包含你的修改的列表。对于程序的清晰度、稳健性和推理来说,创建一个具有正确值的新列表并返回它会更好。否则可能会或可能不会起作用,但是当您可以选择编写明确的东西时,谁愿意编写其语义取决于其他库的实现细节的代码?

于 2012-04-24T08:15:05.017 回答