多线程JAVA中的静态方法行为

时间:2016-08-19 07:45:53

标签: java multithreading concurrency synchronization

我更新了多线程环境中的值

Class TestClass{

    public static TestObject updateTestObject (TestObject testObject )
    {
        testObject.setLatestSequence (testObject.getLatestSequence () + 1);

        return testObject ;
    }

}

该值在另一个类中使用。该函数是同步的,因此一次只能有一个线程进入。

Class parentClass 
{

 void synchronized updateDBSequence()
 {
      // Read old value from DB     
      TestObject testObject = readFromDAO.readTestClass(naturalKey);

     // Access in static manner, Issue ? If two threads go in, the object       
     //the return will have duplicate sequence number in it e.g. first read             
     //1 as latest sequence second also read 1 and both updated it to 2 and save in DB.

    TestClass.updateTestObject (testObject);

    // DAO has already been injected by spring
    // Update value in DB
    testObjectDAO.update (testObject);
  }

当在多线程环境中运行时,有时,从testClass.updateTestObject()方法返回的对象具有重复序列,因此重复序列保存在DB中。我们希望他们永远是独一无二的

为了解决这个问题,函数updateDBSequence()已经同步,但没有解决问题,然后意识到TestClass.updateTestObject()函数可能导致问题,因为它是静态的并且线程在其中我不知道其他线程用什么更新了这个值。

因此,要解决它,Class.function方式访问已更改为其中的实际代码,而不是在代码中调用具有类名的静态函数。

  void synchronized updateDBSequence()
  {
      // Read old value from DB     
      TestObject testObject = readFromDAO.readTestClass(naturalKey);

     // DO not access in static manner 
       testObject.setLatestSequence (testObject.getLatestSequence () + 1);


    // DAO has already been injected by spring
    // Update value in DB
    testObjectDAO.update (testObject);
  }

它会解决这个问题吗?进入静态方法的线程不知道其他线程更新的值是什么,即他们正在处理的对象是共享的,每个都有自己的副本。

1 个答案:

答案 0 :(得分:1)

testObject.setLatestSequence (testObject.getLatestSequence () + 1);

不是原子的。

如果您使用多个updateDBSequence()实例,则

parentClass不是原子的。

您建议的修改(使用实例)不会改变任何东西。 最好的办法是使用交易而不是重新发明轮子。

快速解决方法是在TestClass上进行同步。

 void updateDBSequence()
 {
     synchronized (TestClass.class) {
        // Read old value from DB     
        TestObject testObject = readFromDAO.readTestClass(naturalKey);

        TestClass.updateTestObject (testObject);

        testObjectDAO.update (testObject);

     }
}

这将解决updateDBSequence()的并发调用之间的问题。如果在其他方法中使用TestClassreadFromDAO,则会出现数据竞争条件。