java - 调用同步的 getter 和 setter

标签 java thread-safety synchronized

我正在尝试用方法练习同步关键字。

我编写了以下代码:

加法器类:

public class Adder implements Runnable{
    Counter counter;
    Adder(Counter counter){
        this.counter = counter;
    }
    public void run() {
        for (int i=0; i<100; i++)
            counter.setCount(counter.getCount()+1);
    }
}

计数器类别:

public class Counter {

    private int count = 0;

    public synchronized void setCount(int val){
        count = val;
    }

    public synchronized int getCount(){
        return count;
    }
}

主要:

public class main {

    public static void main(String[] args) {
        Counter counter = new Counter();
        Adder adder = new Adder(counter);
        Thread t1 = new Thread(adder);
        Thread t2 = new Thread(adder);
        t1.start();
        t2.start();
        try {
            t1.join();
            t2.join();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println(counter.getCount());
    }
}

我预计其输出为 200,但它不是确定性的(理论上,可以是 0-200 之间的任何值)。我怀疑问题是我正在使用内联的 getter 和 setter,即

counter.setCount(counter.getCount()+1);

由于某种原因,这“破坏”了我试图通过同步实现的互斥,但我不明白为什么。

我用 count++ 实现了 1 的加法,如下所示:

public synchronized void add1(){
        count++;
}

这有效,也许是因为这样我只使用一个函数而不是两个内联函数。 您能解释一下为什么第一个实现不起作用吗?

最佳答案

调用 getter 和后续调用 setter 是两个独立的操作。 “设置 getter 的结果加一”在这里不是原子的。因此,您完全可以有两个 get 返回相同的值,并且两组相同的值加一。

假设计数100。您有两个线程调用 getter,都获得 100。然后它们都调用 setter,设置 101。所以计数器现在是 101,而不是 102 - 并且两个线程都“在那里”。

因此结果是不确定的,取决于两个线程获取/设置操作的实际顺序。

关于java - 调用同步的 getter 和 setter,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/40963470/

相关文章:

java - 多类别测验应用程序

Java JProgressBar 不通过 setVisible(true) 显示

c - 警报处理程序中 swapcontext 后的段错误

java - 这些线程在哪个对象上同步

java - 为什么要同步Java方法Provider.getService(String type,String algorithm)?

java - 使用 Gilead 保留带有继承的类

java - 如何让 im4java 与 BufferedImage 一起工作

java - 使用java中的synchronous关键字安全访问成员变量

java - 什么时候使用静态类而不是单例模式?

java - 如果没有人调用interrupt(),是否可以忽略InterruptedException?