Java线程:竞争条件与同步

时间:2016-06-10 06:43:22

标签: java multithreading race-condition

即使调用代码块已同步,也会发生竞争条件。再想一想,它似乎是一个锁定问题。请查看以下简单的代码块(代码将更好地解释) -

class CriticalSectionTest {

    public void initWithSync() {
        final CriticalSection cSection = new CriticalSection();

        Thread threadA = new Thread(new Runnable() {
            @Override public void run() {
                synchronized (cSection) {
                    cSection.add(2);
                    System.out.println(
                            "Value after adding from thread-A: " + cSection.getCount());
                }
            }
        });

        Thread threadB = new Thread(new Runnable() {
            @Override public void run() {
                synchronized (cSection) {
                    cSection.add(3);
                    System.out.println(
                            "Value after adding from thread-B: " + cSection.getCount());
                }
            }
        });

        threadA.start();
        threadB.start();

        //Desired output:
        //A: 2
        //B: 5
    }
}

class CriticalSection {
    private long count = 0;

    public void add(long value) {
        /* This method was not made synchronized, intentionally as its done in caller class
         */
        this.count = this.count + value;
    }

    public long getCount() {
        return count;
    }
}

在多次运行中,它会打印以下输出 -

不行

Value after adding from thread-B: 3
Value after adding from thread-A: 5

看起来不错

Value after adding from thread-A: 2 
Value after adding from thread-B: 5

任何解释?还是我错过了一些基础知识?

2 个答案:

答案 0 :(得分:3)

同步不确定执行顺序。它只是保证线程不会同时执行代码。

致电Thread.start()并不立即致电Thread.run();它只是要求线程调度程序在将来的某个时刻运行它。您描述的行为的解释是线程调度程序有时可能在线程A之前开始执行线程B.这是预期的行为。

如果您希望代码按特定顺序依次执行,则在单个线程中完成所有操作会更容易。

答案 1 :(得分:2)

关于每个线程的开始顺序,没有什么是安全的。 Main线程将一个接一个地启动线程但没有任何阻止以下内容:

THREAD A : START
THREAD B : START
THREAD A : WAIT
THREAD B : RUN
THREAD A : RUN
THREAD A : STOP
THREAD B : STOP

threadB有时可能会在threadA之前开始治疗,而这正是您现在所面临的问题。