我开始学习一些Java并发概念并投入使用。
但是这段代码之一超出了我的理解。
public class Count {
private int count = 0;
public synchronized void setCount(int count) {
this.count = count;
}
public synchronized int getCount() {
return count;
}
}
class CountRunner extends Thread {
Count count;
public CountRunner(Count count) {
this.count = count;
}
public void run() {
for (int i = 1; i <= 1000; i++) {
count.setCount(count.getCount() + 1);
}
}
}
class TestCount {
public static void main(String[] args) throws Exception {
Count count = new Count();
CountRunner runnerA = new CountRunner(count);
CountRunner runnerB = new CountRunner(count);
runnerA.start();
runnerB.start();
runnerA.join(); //join statement here
runnerB.join();
System.out.println("count.getCount = " + count.getCount());
}
}
题:
1.结果多次小于2000,为什么?
2.如果删除2 join()语句,为什么count.getCount = 451,甚至更少?
3.我认为删除join()语句不会有任何效果,
因为我已经有了同步方法来每次将一个对象锁定到一个线程?
那么,使用Synchronized和join()有什么意义呢?
最佳答案
这很简单。您可以通过调用getCount + 1来调用setCount方法。在进入该方法之前,运行时将对getCount进行评估(同步),但是在离开getCount并输入setCount时您不必保持锁定,其他线程可以进入调用getCount。因此,不时有两个(或更多取决于您创建的线程数)线程在getCount中具有相同的值。想象一下,线程A在getCount中输入并接收值1。运行时将其执行到胎面B,该胎面B调用getCount并接收相同的值1。线程B将值设置为1并进行了另外50次运行,因此该阶段的计数为50。运行时产生对线程A的执行,该线程以1调用setCount(请记住,它没有设法调用setCount并产生了exec)。现在,A将值设置为1(这是错误的)。
更改您运行的实现,如下所示:
public void run() {
for (int i = 1; i <= 1000; i++) {
synchronized(count){
count.setCount(count.getCount() + 1);
}
}
}