调用同步 getter 和 setter
Invoking synchronized getter and setter
我正在尝试使用方法练习同步关键字。
我写了下面的代码:
加法器class:
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);
}
}
计数器class:
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);
出于某种原因,这个 "breaks" 我试图通过同步实现的互斥,但我不明白为什么。
我用 count++ 实现了 1 的加法,如下所示:
public synchronized void add1(){
count++;
}
这行得通,可能是因为这样我只使用一个函数而不是两个内联函数。 您能解释一下为什么第一个实现不起作用吗?
counter.setCount(counter.getCount()+1);
不是原子的,它涉及 3 个步骤:
(1)读取count
的值
(2) count
加一
(3)写入count
的值
在第一种方法中,您是独立获取锁的,即在一个线程的 get
和 set
调用之间会有其他线程的干扰。所以不能保证第一个线程读到的值和写的时候是一样的。
第二种方式,你是持有锁,上面3个步骤都在执行,所以你不会发现任何问题。
此外,您也可以使用线程安全AtomicInteger class.
来解决您的问题
调用 getter 和后续调用 setter 是两个独立的操作。 "Set the result of getter plus one" 在这里不是原子的。所以你可以完美地让两个get返回相同的值,并且两组相同的值增加一个。
假设 count
是 100
。你有两个线程调用 getter,都得到 100。然后它们都调用 setter,设置 101。所以计数器现在是 101,而不是 102 - 两个线程 "were there" 已经.
所以结果是不确定的,取决于来自两个线程的 get/set 操作的实际顺序。
我正在尝试使用方法练习同步关键字。
我写了下面的代码:
加法器class:
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);
}
}
计数器class:
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);
出于某种原因,这个 "breaks" 我试图通过同步实现的互斥,但我不明白为什么。
我用 count++ 实现了 1 的加法,如下所示:
public synchronized void add1(){
count++;
}
这行得通,可能是因为这样我只使用一个函数而不是两个内联函数。 您能解释一下为什么第一个实现不起作用吗?
counter.setCount(counter.getCount()+1);
不是原子的,它涉及 3 个步骤:
(1)读取count
(2) count
(3)写入count
在第一种方法中,您是独立获取锁的,即在一个线程的 get
和 set
调用之间会有其他线程的干扰。所以不能保证第一个线程读到的值和写的时候是一样的。
第二种方式,你是持有锁,上面3个步骤都在执行,所以你不会发现任何问题。
此外,您也可以使用线程安全AtomicInteger class.
来解决您的问题调用 getter 和后续调用 setter 是两个独立的操作。 "Set the result of getter plus one" 在这里不是原子的。所以你可以完美地让两个get返回相同的值,并且两组相同的值增加一个。
假设 count
是 100
。你有两个线程调用 getter,都得到 100。然后它们都调用 setter,设置 101。所以计数器现在是 101,而不是 102 - 两个线程 "were there" 已经.
所以结果是不确定的,取决于来自两个线程的 get/set 操作的实际顺序。