如果我的Servlet实例变量是StringBuffer类型,它是否是线程安全的? [英] If my Servlet instance variable is of type StringBuffer, is it thread-safe?

查看:142
本文介绍了如果我的Servlet实例变量是StringBuffer类型,它是否是线程安全的?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我要澄清的第一件事是,我知道Servlet是单实例多线程模型。 Container维护实例并为每个要处理的请求创建多个线程,并且所有线程在同一个servlet实例上工作。此外,我们不应该在servlet中维护状态,因为它会导致多线程/并发问题。凉!!如果状态(servlet的成员)本身是线程安全的呢?如下例所示

First thing I wan't to clarify is, I know Servlet is single instance multi-threaded model. Container maintains on instance and creates multiple threads per multiple requests to handle and all the threads work on same servlet instance. Also, we shouldn't maintain state in a servlet as it causes multi-threading/concurrency issues. Cool!! What if the state (member's of servlet) itself is thread-safe?? As in below example

public class MyCrazyServlet extends HttpServlet {
  StringBuffer s1 = new StringBuffer("stackoverflow");
  static StringBuffer s2 = new StringBuffer("stackexchange");
  public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
    String s3 = "I'm safe";
    HttpSession crazySession = request.getSession();
    //more stuff here
  }
}

上面片段,我认为除了crazySession局部变量(HttpSession实例)之外的一切(s1,s2和s3)都是线程安全的

In above snippet, I presume except crazySession local variable (HttpSession instance) everything else (s1, s2 and s3) is thread safe

请更正,如果我的理解是错误的

Please correct, if my understanding is wrong

推荐答案

在给定的片段中, s2 永远不会被修改,所以它必须是安全的。但是现在这不是真正有趣的用例,是吗?

In the given snippet, s2 is never modified, so it must be safe. But this isn't really the interesting usecase now, is it?

StringBuffer 在某种意义上是线程安全的如果两个不同的线程同时修改它,一个调用将等待另一个调用结束,这样两个调用都将完全执行而不会互相搞乱。

StringBuffer is thread safe in the sense that if two different threads modify it concurrently, one call will wait for the other to end, so that both call will be fully executed without messing each other up.

考虑以下内容代码段:

// name is retrieved from the calling session
public void addName (String name) {
    // s2 is defined as:
    //    static StringBuffer s2 = new StringBuffer("stackexchange")
    // by the OP
    s2.append(name);
}

如果您(JavaHopper)和I(Mureinik)同时调用此函数,保证内容不会被扰乱。
根据调用的确切时间和上下文切换, s2 将包含stackexchangeJavaHopperMureinikstackexchangeMureinikJavaHopper

If both you (JavaHopper) and I (Mureinik) call this function concurrently, you are guaranteed that the content won't get scrambled. Depending on the exact timing of the calls and the context-switches, s2 will either contain "stackexchangeJavaHopperMureinik" or "stackexchangeMureinikJavaHopper".

但这是陷阱 - 你需要非常,非常小心你的电话。通常情况下,您需要链接多个调用,例如:

But here's the pitfall - you need to be very, very careful with your calls. More often than not, you'd want to chain several calls, e.g.:

// name is retrieved from the calling session
public void addName (String name) {
    // s2 is defined as:
    //    static StringBuffer s2 = new StringBuffer("stackexchange")
    // by the OP
    s2.append("[").append(name).append("]");
}

在此示例中,每个追加是一个不同的电话。因此,上面描述的两个并发调用可能会产生一个有效的结果,如stackexchange [JavaHopper] [Mureinik],但可能会产生类似的内容。 stackexchange [JavaHopper [Mureinik]]

In this example, each append is a different call. So the two concurrent calls described above may yield a valid result like "stackexchange[JavaHopper][Mureinik]", but may very well yield something like "stackexchange[JavaHopper[Mureinik]]".

总结一下:小心。要非常小心。根据代码的复杂程度,最好自己处理同步。

To summarize: Be careful. Be very careful. Depending on how complicated your code is, it might be a better idea to handle synchronization on your own.

这篇关于如果我的Servlet实例变量是StringBuffer类型,它是否是线程安全的?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆