java 为什么 Servlet 中的实例变量不是线程安全的
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/10261579/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Why instance variable in Servlet is not thread-safe
提问by hqt
When I read Head First Servlet and JSP
, they say that instance variable is non-thread safe.
当我阅读时Head First Servlet and JSP
,他们说实例变量是非线程安全的。
I don't understand this statement so much. For example: I have a servlet which name is ActionServlet.java
. Each time, each user's request is sent to server, container will create a new thread and create new ActionServlet
instance.
我太不理解这个说法了。例如:我有一个名为 .servlet 的 servlet ActionServlet.java
。每次,每个用户的请求被发送到服务器,容器将创建一个新线程并创建新ActionServlet
实例。
ActionServlet
may be has a structure:
ActionServlet
可能有一个结构:
public class ActionServlet extends HttpServlet {
// example of instance variable
Instance variable;
public void processRequest(HttpServletRequest request, HttpServletResponse response) {
// process something relating to instance variable
}
}
So, because all these threads create a new class instance for ActionServlet
, so I don't see any problem here. because instances of these thread is separate of each other.
所以,因为所有这些线程都为 创造了一个新的类实例ActionServlet
,所以我在这里看不到任何问题。因为这些线程的实例彼此分开。
Please figure out where problem when use instance variable in multithread environment.
请找出在多线程环境中使用实例变量时出现的问题。
Thanks :)
谢谢 :)
回答by Will Hartung
The mistake you are making is here:
你犯的错误在这里:
So, because all these threads create a new class instance for ActionServlet, so I don't see any problem here. because instances of these thread is separate of each other.
所以,因为所有这些线程都为 ActionServlet 创建了一个新的类实例,所以我在这里看不到任何问题。因为这些线程的实例彼此分开。
The container does not create a new instance of the Servlet class for each request. It reuses an existing one. This is why they are not thread safe.
容器不会为每个请求创建 Servlet 类的新实例。它重用了一个现有的。这就是为什么它们不是线程安全的。
The Stripes Action Framework DOES create a new instance for each request, so that's an okay assumption under that framework. However, for example, Struts 1 follows the Servlet model and does not create a new action per request.
Stripes Action Framework 确实为每个请求创建了一个新实例,因此在该框架下这是一个不错的假设。但是,例如,Struts 1 遵循 Servlet 模型并且不会为每个请求创建新操作。
That does not mean that the container is limited to a single instance, it in theory can create more than one, but it's not a specified behavior so can not be relied upon. Most of the popular ones do not.
这并不意味着容器仅限于单个实例,理论上它可以创建多个实例,但它不是特定的行为,因此不能依赖。大多数流行的都没有。
回答by dash1e
because all these threads create a new class instance (action.java), so I don't see any problem
因为所有这些线程都创建了一个新的类实例(action.java),所以我没有看到任何问题
You are supposing that every thread create a class instance that will be used only by that thread, that's why you don't have any problem.
您假设每个线程都创建一个仅由该线程使用的类实例,这就是您没有任何问题的原因。
But try to imagine, with your specific sample, that the same instance is accessed from two threads. What's happend if both use in the same time your request
and response
members?
Maybe you will read data from unidentifiable request, and you will write an inconsistent response that mix two parts.
但是尝试想象一下,使用您的特定示例,从两个线程访问同一个实例。如果您request
和response
会员同时使用会发生什么?也许你会从无法识别的请求中读取数据,你会写出一个混合了两部分的不一致的响应。
So in you case too, instance variable are not thread safe, because if two thread access the same instance they can disturb each other.
所以在你的情况下,实例变量也不是线程安全的,因为如果两个线程访问同一个实例,它们会相互干扰。
回答by Juan Alberto López Cavallotti
The thing is, your action.java isn't instantiated always but it is being taken from an instance pool, the same goes for the request threads, they are been taken from a thread pool, so a servlet instance may be shared by multiple requests.
问题是,您的 action.java 并不总是实例化,而是从实例池中获取,请求线程也是如此,它们是从线程池中获取的,因此一个 servlet 实例可能被多个请求共享.