java - 多个线程从不同实例访问实例方法会导致竞争条件吗?

标签 java multithreading race-condition synchronized

我正在尝试理解Java中的同步。 我明白,如果我从 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);

}

}

最佳答案

你是对的,竞争条件存在。但活泼的操作是如此之快,以至于它们不太可能发生 - 并且 synchronized 关键字可能提供同步“帮助”,虽然 JLS 不需要,但隐藏了竞争。

如果你想让它更明显一点,你可以“拼出”count = count + 1代码并进入休眠状态:

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

这应该更容易地显示比赛。 (顺便说一句,我对中断异常的处理不太适合生产代码;但对于像这样的小型测试应用程序来说已经足够了。)

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

关于java - 多个线程从不同实例访问实例方法会导致竞争条件吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/24415118/

相关文章:

java - While 循环不重复

java - Payara 5.2020.4 未启动

multithreading - pthreads - 如何并行化一个作业

sql - 在 SQL Server 中创建连续的发票编号而无需竞争条件

javascript - 应用程序运行时 Mapbox `loaded` 方法错误地返回 false

java - getTitle() 方法在 Chrome 中返回当前页面的标题,但在 Firefox 中使用 Selenium 通过 Java 返回上一页的标题

Java null 取消引用 - 微焦点安全漏洞

c# - 是否可以在 Unity 编辑器中选择性地阻止某些程序集的重新加载?

c++ - 多线程 - 断开 TCP 连接

java - JMM : Why this outcome is illegal?