从不同实例访问实例方法的多个线程应该导致竞争条件?

Kum*_*lok 0 java multithreading synchronized race-condition

我试图理解Java中的Synchornized.我知道如果我从2个不同的线程访问同一个对象的同步方法,一次只能有一个访问.

但我认为如果在2个不同的实例上调用相同的方法,则两个对象都应该能够并行访问该方法.如果从方法访问/修改静态成员变量,这将导致竞争条件.但我无法在下面的代码中看到竞争状况.

有人可以解释一下代码或我的理解是否错误.

有关参考代码,请访问:http://ideone.com/wo6h4R

class MyClass
{
   public static int count=0;

   public  int getCount() 
   {

        System.out.println("Inside getcount()");
        return count;
   }

   public synchronized void incrementCount() 
   {
        count=count+1;
   }


}

class Ideone
{
    public static void main(String[] args) throws InterruptedException {
        final MyClass test1 = new MyClass();
        final MyClass test2 = new MyClass();
        Thread t1 = new Thread() { 
                                public void run()  
                                { 
                                    int k=0;
                                    while (k++<50000000)
                                    {
                                          test1.incrementCount();

                                    } 
                                }
                                };

    Thread t2 = new Thread() { 
                                public void run() 
                                { 
                                    int l=0;
                                    while (l++<50000000)
                                    {
                                            test2.incrementCount(); 

                                    } 
                                }
                                };

    t1.start();

    t2.start();
    t1.join();
    t2.join();
    //System.out.println(t2.getState());
    int x=500000000+500000000;
    System.out.println(x);
    System.out.println("count = " + MyClass.count);

}
Run Code Online (Sandbox Code Playgroud)

}

ysh*_*vit 7

你是对的,存在竞争条件.但是这些活动非常快,以至于它们不太可能发生 - 并且synchronized关键字可能提供同步"帮助",虽然JLS没有要求,但隐藏了比赛.

如果你想让它变得更加明显,你可以"拼出" count = count + 1代码并进入睡眠状态:

public synchronized void incrementCount() 
{
    int tmp = count + 1;
    try {
        Thread.sleep(500);
    } catch (InterruptedException e) {
        e.printStackTrace();
    }
    count=tmp;
}
Run Code Online (Sandbox Code Playgroud)

这应该更容易显示比赛.(我对中断异常的处理利于生产代码,顺便说一下;但对于像这样的小型测试应用来说,这已经足够了.)

这里学到的教训是:竞争条件可能很难通过测试,因此最好真正理解代码并向自己证明这是正确的.

  • "随机(400)+ 100"的睡眠会好得多,但答案是关键.此外,值得注意的是,如果没有睡眠,这几乎不可能在单核机器上发生. (3认同)