简体   繁体   English

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

[英]Are methods declared in servlets are thread-safe or the local variables in servlets are thread safe

I have got to know that there is race around condition in my servlets as I have some globally declared variables which are used in it . 我已经知道servlet中存在条件争用,因为我使用了一些全局声明的变量。 So my question is if I declare those variables in some method apart from doGet or doPost method. 所以我的问题是,是否要在除doGetdoPost方法之外的某些方法中声明这些变量。 Will they be not shared among different threads ? 它们将不会在不同线程之间共享吗?

If yes , how we can avoid race around condition . 如果是的话,我们如何避免争分夺秒的情况。 I want to avoid the use of ThreadLocal and usage of singelThreadModel . 我想避免使用ThreadLocalsingelThreadModel用法。

Here is the example 这是例子

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");

        }
}

NOTE : This is just an example , not the actual code . 注意:这仅是示例,并非实际代码。

Are methods declared in servlets are thread-safe Servlet中声明的方法是否是线程安全的

No. 没有。

or the local variables in servlets are thread safe 或servlet中的局部变量是线程安全的

No. 没有。

I have got to know that there is race around condition in my servlets 我已经知道我的servlet中存在争分夺秒的情况

There is a race condition. 比赛条件。

as I have some globally declared variables which are used in it. 因为我有一些全局声明的变量在其中使用。

You have some instance variables. 您有一些实例变量。

So my question is if I declare those variables in some method apart from doGet() or doPost() method, will they be not shared among different threads? 所以我的问题是,如果我在doGet()doPost()方法之外的其他方法中声明这些变量,这些变量是否不会在不同线程之间共享?

Local variables are local to the method they are declared in. 局部变量对于声明它们的方法是局部的。

If yes, how we can avoid race around condition. 如果是的话,我们如何避免出现条件竞赛。

I can't follow your double negative, but it's still a race condition. 我不能追随你的双重否定,但这仍然是比赛条件。 Don't misuse standard terminology. 不要滥用标准术语。 You need to avoid instance members of a Servlet unless they are common to and shared by all possible concurrent invocations of its methods. 您需要避免Servlet实例成员,除非它们是方法的所有可能的并发调用所共有并共享的。 Per-request variables must be method-local and passed around between methods as parameters or return values. 每个请求变量必须是方法局部的,并且在方法之间作为参数或返回值传递。

I want to avoid the use of ThreadLocal and usage of SingleThreadModel . 我想避免使用ThreadLocalSingleThreadModel用法。

You certainly do. 当然可以 There are no specified thread semantics in a Servlet that would make ThreadLocal work, and SingleThreadModel is deprecated and will be removed. Servlet中没有指定的线程语义可以使ThreadLocal工作,并且不赞成使用SingleThreadModel并将其删除。

A Servlet is a Java class so its already thread - safe if it has no state ( ie if it doesn't have any state variables ) . Servlet是Java类,因此如果它没有状态(即,如果它没有任何状态变量),则它已经是线程安全的。 No extra action is needed from your side. 您无需采取任何额外的措施。

Now , you introduce state variables like - userString1 & userString2 and your servlet can still be thread - safe since String is immutable but you are reassigning its reference for each request so it does not remain thread safe since assignments by one thread might change to some other value by some other thread ( by the time , thread one tries to use it ) . 现在,您引入状态变量,例如userString1userString2并且servlet仍然可以是线程安全的,因为String是不可变的,但是您正在为每个请求重新分配其引用,因此它不会保持线程安全,因为一个线程的分配可能会更改为其他线程其他线程的值(当时,一个线程试图使用它)。 You can have an immutable as state & remain thread - safe , provided you don't reassign its reference the way you doing in someTask method. 您可以拥有不可变的state并保持线程安全,前提是您不必以someTask方法的方式重新分配其引用。

So use those string variables provided its purpose is to pass some constant string to all request threads. 因此,请使用这些字符串变量,前提是其目的是将某个常量字符串传递给所有请求线程。

Also, in your code, you are putting lots of Strings on heap by that assignment expression in someTask method. 同样,在代码中,您通过someTask方法中的赋值表达式将大量字符串放在堆上。

At last, you have to utilize java synchronization constructs to make your class thread safe if you have to use mutable state objects in those methods but again plain Java synchronization constructs are per JVM so you will face issues if deployment has to be distributed on a cluster. 最后,如果必须在这些方法中使用可变状态对象,则必须利用Java同步结构来确保类线程安全,但是每个JVM同样使用普通的Java同步结构,因此如果必须在群集上分发部署,则会遇到问题。 。 Some distributed locking mechanism will be needed in that case. 在这种情况下,将需要一些分布式锁定机制。

If you are declaring a global variable and assigning the values in doGet or doPost method, they will definitely be overriden by different threads calling the servlet. 如果要声明全局变量并在doGet或doPost方法中分配值,则肯定会被调用servlet的其他线程覆盖。 You should not assign values to global variables in servlet method calls. 不应在servlet方法调用中为全局变量分配值。

In your code what is stopping you from declaring the userString1 & userString2 inside method? 在您的代码中,是什么阻止您声明方法里面的userString1userString2 Why do you want to declare them globally? 为什么要全局声明它们? If you want these variables to be used in different methods of the servlet, then simply pass them as method arguments instead of declaring them as global variables. 如果要在Servlet的不同方法中使用这些变量,则只需将它们作为方法参数传递,而不是将它们声明为全局变量。

eg 例如

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.
}

OR 要么

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.
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM