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
的用途。只要阅读它的文档。