1

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.

5
  • 2
    Use a real database sequence. Commented Aug 19, 2016 at 7:53
  • But what about behavior of threads in this scenario ? Commented Aug 19, 2016 at 7:56
  • 1
    void synchronized function updateDBSequence()? That's not Java. Commented Aug 19, 2016 at 7:59
  • Impossible to tell. Too many unknowns. What do the DAOs do. What is naturalKey? What is parentClass and how many instances of thoese are they. Where are transactions, etc. But trying to fix transactional issues with thread synchronization is not the right approach. If you need a globally incrementing sequence, use a database sequence, that's what it's for. But reading all your question and peudo-code, I have a hard time understanding what you're trying to achieve. Commented Aug 19, 2016 at 8:00
  • Parent class is always called by using newInstance Commented Aug 19, 2016 at 10:34

1 Answer 1

1

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.

Sign up to request clarification or add additional context in comments.

3 Comments

Which won't help if TestClass.updateTestObject (testObject); is additionally called somewhere else without syncing ... just a thought.
Then we do not need synchronized updateDBSequence, we can remove synchronized from method signature ?
There are many other methods which are using TestClass and readFromDAO. This means this solution will not work ?

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.