[英]What is the best way to ensure concurrent object calls without locking
I have the following objects: 我有以下对象:
// this class is immutable, acts like container for several properties.
public class MyDataAddOps{
private final boolean isActive;
private final Map<String,Object> additionalProps;
public MyDataAddOps(boolean isActive, Map<String,Object> additionalProps){
this.isActive = isActive;
this.additionalProps = additionalProps;
}
public boolean isActive(){return isActive;}
public Map<String,Object> getAdditionalProps(){ return additionalProps;}
}
// this class acts as "spring" bean that calls load on construction,
// and then another scheduler bean calls the load per some cron expression (once a minute for example)
public class MyDataAddOpsService{
private MyDataAddOps data;
// this method will be executed periodically outside
// via some spring quartz for example
// the quartz is not re-entrant
public void load(){
// opens some defined file and returns content string
String fileData = getFileContent();
boolean isActive = getIsActive(fileData);
Map<String, Object> props = getProps(fileData);
data = new MyDataAddOps(isActive, props);
}
// This method is executed by many workers threads inside the application
public boolean isActive(){
return data.isActive();
}
public final Map<String, Object> getProps(){
return data.getAdditionalProps();
}
}
This approach probably has a race condition where one thread executes isActive()
and another load()
. 这种方法可能具有一个竞争条件,其中一个线程执行isActive()
而另一线程执行load()
。 Although it operates on reference and the object state is not changed. 尽管它在参考上运行并且对象状态未更改。
What is the best solution to support such concurrency? 支持此类并发的最佳解决方案是什么? I would like to avoid syncronized on methods, and also read-write lock. 我想避免方法同步,也避免读写锁定。
Maybe AtomicReference
or volatile
? 也许是AtomicReference
或volatile
? Or maybe it would be better to return only reference to the data itself without proxy methods? 还是最好只返回对数据本身的引用而没有代理方法呢? So no need for locking at all, and all the usage logic is outside this service? 因此,根本不需要锁定,并且所有使用逻辑都在此服务之外吗?
public class MyDataAddOpsService{
private MyDataAddOps data;
public void load(){
....
data = new MyDataAddOps(isActive, props);
}
public MyDataAddOps getData(){
return data;
}
}
Your code has yet to grow towards having a race condition; 您的代码还没有朝着产生竞争条件的方向发展。 currently it contains something much more severe, which is a data race . 当前它包含更严重的东西,这是一场数据竞赛 。 Publishing a reference across threads without inducing a happens before relationship between the write and the future reads means that the reader can see the data object in a partially initialized, inconsistent state. 跨线程发布引用而不会在写入和将来读取之间的关系发生之前发生 ,这意味着读取器可以看到处于部分初始化的不一致状态的数据对象。 Your proposal of a solution does not help with that. 您提出的解决方案对此无济于事。
Once you make the data
field volatile
, only then will you have a race condition between one thread first reading the data
reference, then another thread updating the data
reference, then the first thread reading isActive
from the old data. 一旦你的data
字段中volatile
,只有这样 ,你之间的一个线程首先阅读的竞争条件data
引用,那么另一个线程更新data
的参考,那么第一个线程读取isActive
从旧数据。 This may actually be a benign case for your logic. 对于您的逻辑而言,这实际上可能是一个良性案例。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.