Java Synchronized 结果不正确

两个线程分别执行同一个类的两个方法,且这两个方法都加了 synchronized,但是结果和预期的有出入:

class Demo
{
    public long x = 0;
    public Demo () { }
    synchronized public void foo()  {
        for (int i = 0; i < 9000000; i++) {
            x++;
        }
    }
    synchronized public void bar()  {
        for (int i = 0; i < 9000000; i++) {
            x--;
        }
    }
}

public class Test {
    static Demo d = new Demo();
    public static void main(String[] args)
    {
        Thread t1 = new Thread(new Runnable() {
            @Override
            public void run() {
                d.foo();
                System.out.println("线程1   "+d.x);
            }
        });

        Thread t2 = new Thread(new Runnable() {
            @Override
            public void run() {
                d.bar();
                System.out.println("线程2   "+d.x);
            }
        });

        t1.start();
        t2.start();
        try {
            t1.join();
        } catch (InterruptedException e) {
            e.printStackTrace();

        }
        try {
            t2.join();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }

        System.out.println(d.x);
    }
}

输出:

线程1 8995659
线程2 0
0

居然不是标准的 9000000,这是怎么回事?

阅读 2k
2 个回答

突然明白了……

虽然 foobar 加了 synchronized,但是在 foo结束,System.out.println 输出结果时bar就已经开始执行了,从而导致拿到的值小于预期的 9000000

问题应该是出在t1t2两个线程的join()方法的调用位置上,把代码改成一下格式:

class Demo
{
    public long x = 0;
    public Demo () { }
    synchronized public void foo()  {
        for (int i = 0; i < 9000000; i++) {
            x++;
        }
    }
    synchronized public void bar()  {
        for (int i = 0; i < 9000000; i++) {
            x--;
        }
    }
}

public class Test {
    static Demo d = new Demo();
    public static void main(String[] args)
    {
        Thread t1 = new Thread(new Runnable() {
            @Override
            public void run() {
                d.foo();
                System.out.println("线程1   "+ d.x);
            }
        });

        Thread t2 = new Thread(new Runnable() {
            @Override
            public void run() {
                d.bar();
                System.out.println("线程2   "+d.x);
            }
        });

        t1.start();
        try {
            t1.join();
        } catch (InterruptedException e) {
            e.printStackTrace();

        }

        t2.start();
        try {
            t2.join();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }

        System.out.println(d.x);
    }
}
撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题