Java线程同步,最佳并发实用程序,读取操作
我有一个与java线程相关的问题 举一个非常简单的例子,假设我有两个线程 线程运行StockReader类实例 运行StockAvgDataCollector类实例的线程B 在线程B中,StockAvgDataCollector连续收集一些市场数据,执行一些重平均/操作,并更新成员变量spAvgData 在线程中,StockReader可以使用getspAvgData()方法访问StockAvgDataCollector实例及其成员spAvgData 因此线程A只执行读操作,线程B执行读/写操作 问题Java线程同步,最佳并发实用程序,读取操作,java,multithreading,Java,Multithreading,我有一个与java线程相关的问题 举一个非常简单的例子,假设我有两个线程 线程运行StockReader类实例 运行StockAvgDataCollector类实例的线程B 在线程B中,StockAvgDataCollector连续收集一些市场数据,执行一些重平均/操作,并更新成员变量spAvgData 在线程中,StockReader可以使用getspAvgData()方法访问StockAvgDataCollector实例及其成员spAvgData 因此线程A只执行读操作,线程B执行读/写操作
ReentrantReadWriteLock
,并且在持有锁时不暂停或无超时睡眠,则不会出现死锁。如果您确实执行了不安全的线程操作,或者尝试推出您自己的同步解决方案,那么您将需要担心它StockReader
中持续运行摄取循环ReadWriteLock
在单核处理器上仍然是有益的——无论线程是同时运行还是仅仅由上下文开关交错运行,问题都是一样的
如果你至少不使用某种形式的同步(例如,
volatile
),那么你的读者可能永远看不到任何变化。好吧,当你有多个读者和至少一个作者时,读写锁的整件事真的很有意义。。。因此,您可以保证生动性(如果没有其他线程正在编写,您就不会阻塞任何阅读器线程)。但是,您只有两个线程
如果您不介意线程B读取spAvgData的旧(但未损坏)值,那么我会选择AtomicDouble(或AtomicReference,取决于spAvgData的数据类型)
所以代码应该是这样的
public class A extends Thread {
// spAvgData
private final AtomicDouble spAvgData = new AtomicDouble(someDefaultValue);
public void run() {
while (compute) {
// do intensive work
// ...
// done with work, update spAvgData
spAvgData.set(resultOfComputation);
}
}
public double getSpAvgData() {
return spAvgData.get();
}
}
// --------------
public class B {
public void someMethod() {
A a = new A();
// after A being created, spAvgData contains a valid value (at least the default)
a.start();
while(read) {
// loll around
a.getSpAvgData();
}
}
}
是的,同步很重要,你需要考虑两个参数:SPAVGDATA变量的可见性和它的更新的原子性。为了保证线程A在线程B中对spAvgData变量的可见性,可以将该变量声明为
volatile
或作为一个变量。此外,您还需要使用同步和锁定来保护更新的操作是原子的,以防涉及更多不变量,或者更新操作是复合操作。如果只有线程B正在更新该变量,则不需要同步,并且可见性应足以让线程A读取该变量的最新值。很抱歉,我不知道。刚刚接受了我之前所有的问题。感谢您指出这一点。当然,Java规范保证对int(及更小)和引用的更新是原子的,因此易失性int或对象引用可以工作,后者提供了作者正在替换的对象。感谢大家的回答,我认为所有答案都是好的,值得同等接受。但是stackoverflow只允许接受一个答案。