这段代码中的 StringBuilder 变量线程安全吗?

发布于 2024-09-25 05:51:29 字数 355 浏览 3 评论 0原文

考虑下面的 struts Action 类,我在其中的执行方法中使用 StringBuilder 变量。我的问题:变量 sb 是否是线程安全的?

public DemoAction extends Action
{
    ......

    public ActionForward execute(.....)
    {
       StringBuilder sb = new StringBuilder();
    }
}

如果在execute() 之外声明相同的变量sb 会怎样?请记住,WebContainer 中只有一个 DemoAction 对象。?

Consider the below struts Action class in which, I am using a StringBuilder variable inside the execute method. My question: Is the variable sb threadsafe or not?

public DemoAction extends Action
{
    ......

    public ActionForward execute(.....)
    {
       StringBuilder sb = new StringBuilder();
    }
}

What if the same variable sb declared outside the execute(). Remember there will be only one object for DemoAction in WebContainer.?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(7

笨死的猪 2024-10-02 05:51:29

局部变量是线程安全的,只要没有其他线程以某种方式获取对同一字符串生成器实例的引用,它就是线程安全的。

Local variables are thread safe, as long as no other thread somehow gets a reference to the same string builder instance, it’s thread safe.

疾风者 2024-10-02 05:51:29

它是线程安全的,因为您只在方法的范围内创建和使用它,因此引用将存储在每个线程本地的堆栈空间中

It is threadsafe because you only create and use it in the scope of the method so reference will be stored in stack space which is local for each thread

我不吻晚风 2024-10-02 05:51:29

是的,局部变量本质上是线程安全的。每个线程都有自己的副本。

Yes, local variables are inherently thread-safe. Every thread gets its own copy.

煮茶煮酒煮时光 2024-10-02 05:51:29

来自 Java 6 StringBuilder Javadoc

此类提供了与 StringBuffer 兼容的 API,但不保证同步。此类设计为在单个线程使用字符串缓冲区的地方(通常是这种情况)用作 StringBuffer 的直接替代品。如果可能,建议优先使用此类而不是 StringBuffer,因为在大多数实现下它会更快。

这意味着该类不是线程安全的,您应该更喜欢 StringBuffer 您知道该变量将被并发访问。

但是,在这种情况下,您可以保证您的 StringBuilder 只能从一个线程访问,因为它是局部变量而不是实例变量。有关说明,请参阅问题“线程安全和局部变量”

From the Java 6 StringBuilder Javadoc:

This class provides an API compatible with StringBuffer, but with no guarantee of synchronization. This class is designed for use as a drop-in replacement for StringBuffer in places where the string buffer was being used by a single thread (as is generally the case). Where possible, it is recommended that this class be used in preference to StringBuffer as it will be faster under most implementations.

This means that the class is not threadsafe, and you should prefer StringBuffer where you know the variable will be accessed concurrently.

However, you can guarantee in this case that your StringBuilder will be accessed only from one thread, because it is local variable rather than an instance variable. See the question 'Thread safety and local variables' for an explanation.

北音执念 2024-10-02 05:51:29

这是安全的。该变量是 execute() 方法的本地变量,并且在每次调用该方法时都会创建,因此在多线程环境中,每个线程都可以拥有自己的、单独的 sb 变量副本。

It is safe. This variable is local to execute() method and is created every time this method is called, so in multithread environment every thread can have its own, separate copy of sb variable.

哑剧 2024-10-02 05:51:29

StringBuilder 不是线程安全的,但只要您从单个线程使用它,就不必担心它。即使您从两个线程进行访问,您也可以通过用同步块封闭关键部分来轻松使其线程安全,例如,

private StringBuilder sb = new StringBuilder();

void appendSomething(String v) {
  synchronized (sb) {
    sb.append("You entered ");
    sb.append(v);
  }
}

如果整个方法是关键部分,您可以在该方法上说同步

synchronized void appendSomething(String v) {
 sb.append("You entered ");
 sb.append(v);
}

注意我显式编写了两个附加语句来演示仅使用线程安全的 StringBuffer 不会使代码线程安全。如果您使用 StringBuffer 运行两个线程,则每个追加可能会同步,但仍然有可能发生竞争条件。

private StringBuffer sb = new StringBuffer();

void appendSomething(String v) {
 sb.append("You entered ");
 // Race condition!!!
 sb.append(v);
}

因此,两个写入“hello”和“world”的线程可能会导致输出“您输入了您输入了helloworld”,因为每个附加都受到保护,而不是整个操作。

使用同步类的效率也较低。例如,在上面的示例中,对追加的两次调用都是同步的,因此除了竞争条件之外,我还必须锁定对象两次,而不是使用非同步类锁定对象一次。

StringBuilder isn't thread safe, but as long as you use it from a single thread you don't have to worry about it. Even if you do access from two threads you can easily make it thread safe by enclosing the critical section with a synchronized block, e.g.

private StringBuilder sb = new StringBuilder();

void appendSomething(String v) {
  synchronized (sb) {
    sb.append("You entered ");
    sb.append(v);
  }
}

If the entire method is the critical section you can say synchronized on the method

synchronized void appendSomething(String v) {
 sb.append("You entered ");
 sb.append(v);
}

Note I explicitly wrote two append statements to demonstrate that just using thread safe StringBuffer wouldn't make code thread safe. If you ran two threads with a StringBuffer then each append might be synchronized but it would still be possible for race conditions to occur.

private StringBuffer sb = new StringBuffer();

void appendSomething(String v) {
 sb.append("You entered ");
 // Race condition!!!
 sb.append(v);
}

So two threads writing "hello" and "world" might result in the output "You entered You entered helloworld" because each append is protected not the whole action.

Using synchronized classes are also less efficient. For example in the above example, both calls to append are synchronized so in addition to a race condition I have to lock the object twice compared to once with the non-synchronized class.

一笑百媚生 2024-10-02 05:51:29

来自规范

StringBuilder 的实例对于多线程使用是不安全的。如果需要这样的同步,那么建议使用StringBuffer。

但正如 Konrad Rudolph 指出的,在你的情况下它是一个局部变量,所以你应该没问题

From the spec:

Instances of StringBuilder are not safe for use by multiple threads. If such synchronization is required then it is recommended that StringBuffer be used.

But as Konrad Rudolph pointed out, in your case it's a local variable so you should be fine

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文