java - 以异步方式访问时,单例中的类级别变量是否会导致脏读?

标签 java spring multithreading spring-boot

如果一个被@Service注解的类的异步方法被一个被注解为@RestController的类调用,我们的服务类的全局变量会在线程间共享吗?

我问这个是因为我知道每个线程都会得到它正在执行的类的本地副本,如果单例类中的共享全局变量不是易变的,它是否仍会共享值或导致脏读或写。

需要注意的是,这两个变量是基元,所以我假设它们将存储在堆栈上而不是堆上。

由于每个线程都将获得类的副本,因为变量是原始变量,所以不会每个线程都在堆栈而不是堆上进行本地更新吗?

@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.");
        }

    }

}    

最佳答案

服务将在线程之间共享,它的成员变量也是如此。如果使用 volatile 关键字,这将强制线程从/向主内存而不是缓存读取/写入值 details here .但是,如果多个线程更新该值,这并不能防止脏读/写。

如果值不应该在线程之间共享,你可以使用 ThreadLocal .每个线程都会有一个独立的值副本。如果可能,您还应该考虑在方法内部使用局部变量。

如果需要安全地访问线程间的值,可以使用Atomic variables或使用 synchronized 关键字或锁 details .

关于java - 以异步方式访问时,单例中的类级别变量是否会导致脏读?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/64016561/

相关文章:

java - Tomcat 服务器中的 Log4j FileAppender 问题

java - 调用 HashMap 对象的方法

java - 试图禁用可聚焦,不工作,android

spring - 在 Spring MVC 和 Hibernate 中使用通用 DAO 和通用服务模式的优缺点是什么

c++ - 使用 CRITICAL_SECTION 锁定/解锁功能

c++ - 如何在 QThread 上创建 QTcpServer 然后从主线程中停止它

java - 未处理异常的看似虚假的错误消息

java - Spring Roo 'Encountered " "void" "void "“”

java - 基于时间戳的逐出缓存

java - 在 Java 中,不允许具有 run() 方法的类作为 new Thread() 的参数