在servlet中声明的方法是线程安全的还是servlet中的局部变量是线程安全的

时间:2017-07-20 08:55:23

标签: java multithreading servlets

我必须知道我的servlet中存在争用条件,因为我在其中使用了一些全局声明的变量。所以我的问题是,如果我在某种方法中使用doGetdoPost方法声明这些变量。它们不会在不同的线程之间共享吗?

如果是的话,我们如何才能避免种族问题。我想避免使用ThreadLocal和使用singelThreadModel

以下是示例

public class UserServlet extends HttpServlet {


    private String userString1 = "";
    private String userString2 = "";


    public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        someTask(request, response);
    }

    public void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        someTask(request, response);
    }

    public void someTask(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException
    {
        userString1 = request.getParameter("someParameter");
        userString2 = request.getParameter("someParameter");

        }
}

注意:这只是一个示例,而不是实际代码。

3 个答案:

答案 0 :(得分:0)

  

servlet中声明的方法是否是线程安全的

没有

  

或servlet中的局部变量是线程安全的

没有

  

我必须知道我的servlet中存在种族问题

种族条件。

  

因为我在其中使用了一些全局声明的变量。

您有一些实例变量。

  

所以我的问题是,如果我在某种方法中使用-Path C:\Temp\doGet()方法声明这些变量,它们是否会在不同的线程之间共享?

局部变量是声明它们的方法的本地变量。

  

如果是的话,我们怎样才能避免因种族问题而竞争。

我不能跟随你的双重否定,但它仍然是种族条件。不要滥用标准术语。您需要避免doPost()的实例成员,除非它们对其方法的所有可能的并发调用是共同的并且共享。每个请求变量必须是方法本地的,并在方法之间作为参数或返回值传递。

  

我希望避免使用Servlet和使用ThreadLocal

你当然可以。 SingleThreadModel中没有指定的线程语义可以使Servlet正常工作,ThreadLocal已弃用且将被删除。

答案 1 :(得分:0)

Servlet是一个Java类,因此如果它没有状态(即它没有任何状态变量),它已经是线程安全的。您无需采取额外措施。

现在,您要引入状态变量,例如 - userString1& userString2并且您的servlet仍然可以是线程安全的,因为String是不可变的,但是您为每个请求重新分配其引用,因此它不会保持线程安全,因为一个线程的赋值可能会更改为其他值一些其他线程(当时,线程尝试使用它)。你可以拥有一个不可变的状态&保持线程安全,前提是您不要像someTask方法那样重新分配其引用。

因此,使用这些字符串变量,其目的是将一些常量字符串传递给所有请求线程。

此外,在您的代码中,您通过someTask方法中的赋值表达式在堆上放置了大量字符串。

最后,如果必须在这些方法中使用可变状态对象,则必须利用java同步构造来使类线程安全,但是每个JVM再次使用普通Java同步构造,因此如果必须分发部署,则会遇到问题在群集上。在这种情况下将需要一些分布式锁定机制。

答案 2 :(得分:0)

如果要声明全局变量并在doGet或doPost方法中分配值,则它们肯定会被调用servlet的不同线程覆盖。 不应该在servlet方法调用中为全局变量赋值。

在您的代码中阻止您声明userString1& userString2里面的方法?为什么要在全球范围内声明它们?如果您希望在servlet的不同方法中使用这些变量,那么只需将它们作为方法参数传递,而不是将它们声明为全局变量。

e.g。

public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
    String userString1 = request.getParameter("someParameter");
    String userString2 = request.getParameter("someParameter");
    someTask(request, response, userString1, userString2);
}

public void someTask(HttpServletRequest request, HttpServletResponse response, String userString1, String userString2) throws ServletException, IOException {
    //do whatever you want with these variables.
}

public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
    someTask(request, response);
}

public void someTask(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
    String userString1 = request.getParameter("someParameter");
    String userString2 = request.getParameter("someParameter");

    //do whatever you want with these variables.
}