java中的实例变量和线程安全性

时间:2016-08-16 16:55:29

标签: java thread-safety instance

下面是一个示例类(从我正在测试的类中修改过),我想知道这是否是一个线程安全的类。

我看到其他帖子和博客的答案是实例变量不一定是线程安全的。 (大多数示例用原始类型显示)

当我在方法之外创建OutputResponse对象并从soapui加载测试它失败了,但是当我在方法中创建对象时,负载测试总是成功。

@Service
public class ExampleProvider {

    private OutputResponse outputResponse;

        @Post
        @Path("/test")
        @Consumes("application/json")
    @Produces("application/json")
        public OutputResponseEntity execute (InputRequest inputRequest) {

        outputResponse = new OutputResponse();
            outputResponse.setSomeValue("this is test");
            populateOutputResponse();
        }

        private OutoutResponseEntity<OutputResponse> populateOutputResponse () {
            if(null != inputRequest) {
                outputResponse.setSomeOtherValue(inputRequest.getName());
            }
            return new OutputResponseEntity(outputResponse,httpstatus.OK);
        }
}

2 个答案:

答案 0 :(得分:0)

您发布的代码似乎不太正确,从语法上讲 - 您的意思是:

public OutputResponseEntity execute (InputRequest inputRequest) {
    outputResponse = new OutputResponse();
    outputResponse.setSomeValue("this is test");
    return populateOutputResponse(inputRequest);
}

假设这就是你的意思,那么似乎多个线程正在使用ExampleProvider的相同实例。这可以解释为什么将outputResponse本地化为execute(然后您可能希望将其传递给populateOutputResponse)来修复您的测试。

如果多个线程使用相同的ExampleProvider实例,那么,正如您的代码现在一样,outputResponse也在这些线程之间共享,并且没有进行同步以防止竞争条件。所以,这样的事情可能会发生:

  • 主题1在setSomeOtherValue(...)
  • 的共享实例上完成outputResponse
  • JVM上下文切换到线程2并在setSomeValue(...)的同一实例上完成outputResponseoutputResponse现在包含来自线程1和2的状态
  • JVM上下文切换回线程1,然后线程1根据此混合状态对象创建OutputResponseEntity

如果你使outputResponse方法的execute本地化并且只是传递它,它实际上变成了线程本地内存,因此每个线程你将拥有该对象的单独实例。这可能是你想要的;如果您不需要在线程之间共享信息,只需将其设置为本地var即可。如果你确实需要在线程之间协调集合/获取(在这个简单的例子中似乎不是这种情况),那么你需要进行某种同步和/或更好地设计程序流程(取决于你的需要)。

答案 1 :(得分:0)

此类在设计上不是线程安全的。但它在一些框架中显然被用作组件。不可能,这个框架确保线程之间不共享ExampleProvider的实例。如果是这种情况,那么您班级的线程安全性不是问题,也不会影响您的测试结果。