Can class level variables in a singleton cause dirty reads when accessed in an async manner?

Viewed 221

If an async method of an @Service annotated class is called via a class annotated as @RestController, will the global variables of our service class be shared between threads?

I ask this because I understand that each thread gets a local copy of the class its executing, and if the shared global variable in a singleton class is not volatile, will it still share values or cause dirty reads or writes.

Point to note is that these two variables are primitives, so I assume that they will be stored on the stack and not on the heap.

As each thread will get a copy of the class, as the variables are primitive, wont each get updated locally on the stack instead of the heap?

@RestController
@RequestMapping(value = "test/v1.0/myputcall")
public class MyController {

    @Autowired
    MyServiceImpl myServiceImpl;

    @PutMapping(consumes = MediaType.APPLICATION_JSON_VALUE)
    public ResponseEntity<String> activate(@RequestBody UserDTO user) {
        
        //Controller calls the async activate method in singleton service class.
        myServiceImpl.activate(user.userType, user.userID);

    }

}


@Service
public class SwitchServiceImpl{

    private int retryCount = 0;
    private boolean updateRequired = false;

    @Async
    public void activate(String userType, String userId){

        if(userType=="prod"){
            updateRequired=true;
        }

        if(updateRequired){
            tryUpdateWithRetry();
        }

private tryUpdateWithRetry(){
            for(;count<3;retryCount++){
                //call some other app
                int status = UpdateUser.update(userId);
                if(status==0){
                    return;
                }
            }
        log.info("update attempted thrice, non zero return status.");
        }

    }

}    
1 Answers

The service will be shared between threads, so will be its member variables. If you use the volatile keyword, this will force the thread to read/write the value from/to the main memory instead of cache details here. However this is not preventing dirty read/write if several threads update the value.

If the value should not be shared at all between threads, you can use ThreadLocal. Each thread will have an independent copy of the value. You should also consider to use local variable inside the method if possible.

If you need to access the value between threads safely, you can use Atomic variables or use synchronized keyword or locks details.

Related