提问者:小点点

字符串的加号运算符的线程安全,包括优化


这篇文章说a=b相当于

a = new StringBuilder()
    .append(a)
    .append(b)
    .toString();

假设我有以下代码:

public class MultiThreadingClass extends SomeThirdPartyClassThatExtendsObject{
    public void beginmt(String st) throws IOException {
        //st is a thread number
        st = new File("c:\\somepath").getCanonicalPath()+"\\"+st;
        System.out.println(st);
    }
}

假定在MultiThread类的单个实例上同时运行多个线程(线程号为1到15500)。是否有这样的情况,它可以打印以下内容,即一些线程号丢失,一些数字加倍?

c:\somepath\2
c:\somepath\1
c:\somepath\1
c:\somepath\4
c:\somepath\5
c:\somepath\6
c:\somepath\7
c:\somepath\8
c:\somepath\8
c:\somepath\10
...

编辑:

可以安全地说,运营商不会卷入一些不安全的出版物问题吗?我认为StringBuilder可以优化成类似实例变量的东西,在这种情况下,它可以不安全地发布。

编辑2:

就JLS、上述post和上述代码的类似类文件而言,要使用的StringBuilder似乎必须包含在不同的StackFrame中。然而,我仍然想检查某种形式的积极优化是否会导致StringBuilder以某种方式被集中式StringBuilder取代。这听起来是可能的,因为当优化器预测一个对象只是以一种非常量的方式实现的时候,而实际上这样的对象可能是常量的时候,优化器进行优化听起来是合乎逻辑的。

找到了stringopts。cpp,但尚未找到充分检查的时间。我希望能找到关于这个源文件细节的答案。

编辑3:

我仍然在寻找答案,包括关于可变对象的积极内联的代码。


共3个答案

匿名用户

不,不同线程之间没有共享状态,因此您描述的情况不会发生。

相反,如果st是该类的成员变量,而不是作为参数传递,并且递增——那就不同了。

它现在的工作原理是,st将被放在执行堆栈上,每个线程都有自己的执行堆栈,它们不共享那里的东西。因此,每个线程都有自己的st值。当它是一个类的成员变量时,它在内存中(单个值),所有线程都会尝试使用它(同一个值)。

@编辑:我想如果您使用相同的值多次调用该方法也是可能的:-)

匿名用户

是否有这样的情况,它可以打印以下内容,即一些线程号丢失,一些数字加倍?

st是一个方法局部变量,而且st也不会超出方法的作用域,因此它是线程安全的。因此,多线程对st没有影响。消息可以按顺序打印,具体取决于哪个线程在什么时候运行该方法。

匿名用户

由于线程之间不共享任何字段,打印顺序可能会有所不同,但不应出现任何与线程安全(竞争条件)有关的问题。