2016-06-10 58 views
-1

即使调用代码块已同步,竞态条件也会发生。再次想到,这似乎是一个锁定问题。请看看下面这个简单的代码块(代码将更好地解释它) -Java线程:争用条件vs同步

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 

任何解释?还是我缺少一些基础知识?

+3

同步不会确定执行顺序。它只是保证线程不会同时执行代码。如果您希望代码按特定顺序并按顺序执行,请勿使用多个线程。 –

+1

另一种说法Andy Yassin在这里已经说过的话:同步不是为了防止数据竞争。这是为了防止数据竞争做_harm_。如果你的程序如此严重同步以至于没有数据竞争的可能,那么你最好使它成为单线程。 –

回答

3

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

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

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

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有时前开始治疗,这就是你面对的现在。