Aiden
Aiden

Reputation: 460

Static method behavior in multithreaded JAVA

I update a value in multithreaded enviornment

Class TestClass{

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

        return testObject ;
    }

}

The value is used in another class like this. The function is synchronized so that only one thread can go in it at a time.

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);
  }

When this is run in multithreaded enviornment, sometimes, the object return from testClass.updateTestObject () method has duplicate sequence and thus duplicate sequences are saved in DB. We want that they are always unique

To overcome this, function updateDBSequence () has been made synchronized, which did not solve the issue, then it was realized that TestClass.updateTestObject () function might be causing the issue, as it is static and the threads going in it will not know what other thread has updated the value with.

So to resolve it, the Class.function manner access was changed with actual code in it instead of calling a static function with class name in the code.

  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);
  }

Will it solve the issue ? Do threads going in a static method do not know what the other thread updated value i.e. the object they are working on is on shared and each has its own copy.

Upvotes: 1

Views: 641

Answers (1)

UmNyobe
UmNyobe

Reputation: 22890

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

Is not atomic.

updateDBSequence() is not atomic either if you are using more than one instance of parentClass.

The modification you propose (using an instance) will not change a thing. The best thing to do would be to use transactions and not reinvent the wheel.

A quick fix will be to synchronize on TestClass.

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

        TestClass.updateTestObject (testObject);

        testObjectDAO.update (testObject);

     }
}

This will solve the issue between concurrent calls of updateDBSequence(). There will be data race conditions if TestClass or readFromDAO are used in another methods.

Upvotes: 1

Related Questions