Java 有没有办法在AtomicReference上设置锁

Java 有没有办法在AtomicReference上设置锁,java,concurrency,Java,Concurrency,我想这样做: 读取原子引用中的值 基于旧值执行复杂逻辑以创建新值 替换AtomicReference中的值 在这个过程中,我希望其他线程等待,直到这是完成。所以我需要在线程上放置一个读锁,并在逻辑完成后释放锁 以下是我的尝试: AtomicReference<String> version = new AtomicReference<>(); String v = version.get(); // Is there way to put a read lock he

我想这样做:

  • 读取原子引用中的值
  • 基于旧值执行复杂逻辑以创建新值
  • 替换AtomicReference中的值
在这个过程中,我希望其他线程等待,直到这是完成。所以我需要在线程上放置一个读锁,并在逻辑完成后释放锁

以下是我的尝试:

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
AtomicReference版本=新的AtomicReference();
字符串v=version.get();//有没有办法在这里设置一个读锁,这样当其他线程尝试读取它时,它们必须等到当前线程完成
如果(v.equals(“old”){
字符串newVersion=getNewVersion();//执行复杂的逻辑
version.set(新版本);
}
//在这里开锁

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

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

AtomicReference版本=新的AtomicReference();
version.updateAndGet(v->{
如果(v.equals(“old”)){
返回getNewVersion();
}
否则{
返回v;
}
});
该方法利用原子指令来实现

该方法的一个简单实现是:

public T updateAndGet(一元运算符f){
T curr,下一个;
做{
curr=get();
下一步=f.应用(当前);
}而(!compareAndSet(curr,next));
下一步返回;
}
如果第一个给定参数等于实际当前值,则方法
compareAndSet
(即访问基础CAS指令的外观)返回
true
,否则返回
false
。如果第一个给定参数等于实际的当前值,则当前值将替换为第二个参数(比较和交换)

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

  • getNewVersion
    可能会多次运行。当当前值被介于
    curr=get()之间的另一个线程更改时,就会发生这种情况
    和CAS调用
  • curr=get()之间发生的读取
    和CAS调用得到的是旧值,而不是您的想法中的新值。但是这个时间跨度很小,你不应该担心
  • 不涉及锁,这是使用
    AtomicXXX
    类的最大好处之一。你希望他们是轻量级和快速

只是想说明一下:这不会锁定原子引用,因为这是不可能的。它只是
字符串old的语法糖;do{old=version.get();}while(old.equals(“old”)&&!version.compareAndSet(old,getNewVersion())在Java8之前应该使用的循环。顺便说一句,您可以将其简化为
version.updateAndGet(v->v.equals(“old”)?getNewVersion():v)这正是原子引用::updateAndGet
的用途。只要阅读它的文档。