如何同步线程中的getter和setter


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最终,将是线程安全的。

最新更新