调用synchronized getter和setter

时间:2016-12-04 20:49:13

标签: java thread-safety synchronized

我正在尝试使用方法练习synchronize关键字。

我写了以下代码:

加法类:

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 inline,即

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

由于某种原因,这&#34;打破&#34;我试图通过同步实现的互斥,但我不明白为什么。

我用计数++实现了1的加法:

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

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

2 个答案:

答案 0 :(得分:1)

<div disabled="disabled" id="someDisplay1" style="display: none;"> <div class="form-group"> <label>Display 1</label> <input name="TextBox1" style="display: none;" type="text" value="" /> </div> </div> 不是原子,它涉及3个步骤:

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

的值

(2)在count

中添加一个

(3)写下count

的值

在第一种方法中,您将独立获取锁,即,在一个线程的countget调用之间,将存在其他线程的干扰。因此,您无法保证第一个线程读取值与写入时相同。

在第二种方法中,您持有锁并执行上述所有3个步骤,因此您不会发现任何问题。

此外,您还可以使用threadsafe AtomicInteger类来解决您的问题。

答案 1 :(得分:1)

调用getter并随后调用setter是两个独立的操作。 &#34;设置getter的结果加一个&#34;这里不是原子的。所以你可能完全有两个返回相同的值,两个相同的值增加一个。

假设count100。你有两个调用getter的线程调用,都得到100.然后他们都调用setter,设置101.所以计数器现在是101,而不是102 - 并且两个线程&#34;都在那里&#34;已经

所以结果是非确定性的,取决于两个线程的get / set操作的实际顺序。