首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >有没有办法在AtomicReference上设置锁?

有没有办法在AtomicReference上设置锁?
EN

Stack Overflow用户
提问于 2020-10-29 14:34:28
回答 1查看 666关注 0票数 1

我想这么做:

  • 读取AtomicReference中的值
  • 基于旧值执行一个复杂的逻辑来创建一个新的值
  • 替换AtomicReference中的值

在此过程中,我希望其他线程等待,直到完成。因此,我需要在线程上放置一个读锁,并在逻辑完成后释放锁。

以下是我的尝试:

代码语言:javascript
复制
AtomicReference<String> version = new AtomicReference<>();
String v = version.get(); // Is there way to put a read lock here so that when other thread try to read it, they will have to wait until the current thread finish
if (v.equals("old")) { 
   String newVersion = getNewVersion(); // execute a complex logic
   version.set(newVersion);
}
// release the lock here
EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2020-10-29 14:59:38

像这样阻塞所有读取线程(通过get)是不可能的。为此,您需要使用其他工具,并且需要在使用version的任何地方使用它们。

与您的想法最接近的是使用AtomicReference的原子方法,比如updateAndGet

代码语言:javascript
复制
AtomicReference<String> version = new AtomicReference<>();
version.updateAndGet(v -> {
    if (v.equals("old")) {
        return getNewVersion();
    }
    else {
        return v;
    }
});

该方法利用原子CAS指令实现非阻塞同步

这种方法的一个简单实现是:

代码语言:javascript
复制
public T updateAndGet(UnaryOperator<T> f) {
    T curr, next;
    do {
        curr = get();
        next = f.apply(curr);
    } while (!compareAndSet(curr, next));
    return next;
}

如果第一个给定的参数等于实际的当前值,则方法compareAndSet (即访问底层CAS指令的外观)返回true,否则为false。如果第一个给定的参数等于实际的当前值,则用第二个参数(比较和交换)替换当前值。

现在我为什么要解释这个?因为使用updateAndGet很接近您想要的,但不同的是:

  • 可能发生的情况是,getNewVersion一次运行更多。当在curr = get();和CAS调用之间的另一个线程更改当前值时,就会发生这种情况。
  • curr = get();和CAS调用之间进行的读取将得到旧值,而不是像您的想法中那样的新值。但是这个时间段很小,你不应该担心它。
  • 不涉及锁,顺便说一下,这是使用AtomicXXX类的最大好处之一。你想让它们轻巧快速。
票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/64593262

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档