我开始学习一些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);
      }
    }
}

10-08 02:04