public class IntermediateMessage {
private final ReentrantReadWriteLock readWriteLock = new ReentrantReadWriteLock();
private final Lock read = readWriteLock.readLock();
private final Lock write = readWriteLock.writeLock();
private volatile double ratio;
public IntermediateMessage(){
this.ratio=1.0d;
}
public IntermediateMessage(double ratio){
this.ratio = ratio;
}
public double getRatio(){
read.lock();
try{
return this.ratio;
}
finally{
read.unlock();
}
}
public void setRatio(double ratio){
write.lock();
try{
this.ratio = ratio;
}
finally{
write.unlock();
}
}
}
我有这个对象。我在我的应用程序中有一个这个对象的实例,一个线程正在写入比率变量,而其他线程正在读取比率。这是保护比率变量的正确方法吗?我是否需要将比率申报为易失性?
你需要锁吗?根据您所描述的有限需求,很可能不会。
- 你只有一个线程在写。
- 这意味着变量值永远不会因为相互竞争的编写器相互"殴打"而"过时"(没有可能的竞争条件)。因此,当单独考虑单个变量时,不需要锁来保证完整性。
- 您没有提到是否需要对多个变量进行某种形式的原子性、一致性修改。我想它不是。
- 如果
ratio
必须始终与其他变量保持一致(例如在其他对象中)-即,如果一组变量必须作为一个组同步更改,没有人读取只是部分更改- 则需要锁来为变量集提供原子一致性。然后,必须在单个锁定区域内同时修改一致的变量,并且在读取任何这些变量集之前,读取器必须获得相同的锁(如果需要,在阻塞状态下等待)。 - IF比率可以在任何时候作为一个单独的变量,不需要与其他变量保持一致,那么不需要锁定,给一组变量原子一致性。
- 如果
是否需要volatile修饰符?嗯,是的!
- 有多个线程正在读取。
- 这个变量可以在任何时刻改变,包括即将被读取之前的瞬间。
-
volatile
修饰符用于多线程应用程序,以保证"读"读的值总是与"写"写的值匹配。
您在同步上做了一些过度的工作,这将导致一些效率低下。
java关键字"volatile"意味着变量不会被缓存,它将被多个线程同步访问。
所以你锁定了一个默认已经同步的变量。
因此,您应该要么删除volatile关键字,要么删除可重入锁。
对于原始值的读写,仅使用volatile
就足够了
假设两个线程正在尝试对同一个对象进行读写,并且您希望保持数据完整性。让你的getter和setter同步。当方法被同步时,只有一个线程能够调用同步方法。当一个线程执行其中一个同步方法时,其他线程将不能调用任何同步方法。在你的例子中,如果你有get &设置方法同步,你可以确定,如果一个线程正在读/写,没有其他线程可以做读/写。
希望有帮助!
使ratio
最终,将是线程安全的。