String是线程安全的吗?那String岂不是不能进行同步?

发布于 2022-09-04 07:06:03 字数 375 浏览 27 评论 0

  1. 我们知道不变对象是指一旦创建不能修改内部状态的对象,因为不变对象没有提供可供修改内部状态的方法,所以不变对象是线程安全的。但是String,当然包括其他的基本数据的包装类,如Integer/Long/Float等等,也是不变对象,但却是可以修改值的,这怎么保证线程安全?

public class Test{

private String str;

public void test(){
        if(("").equals(str)){  //多个线程同时判断,可能导致多次执行
            str = "1";
            //do something
        }
}

}

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

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

发布评论

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

评论(2

满身野味 2022-09-11 07:06:03

重新找个可以锁住的对象,锁住它再修改String。

private String lock = new Object();
private String str;
public void test(){
    synchronized(lock) {
        if(("").equals(str)){  //多个线程同时判断,可能导致多次执行
            str = "1";
            //do something
        }
    }
}
凉城已无爱 2022-09-11 07:06:03

Java中,String类型对象本身是不可变的。因为String会被存储到一个叫做常量池的内存区域。
比如

        String a="test";
        String b="test";
        System.out.println(a==b);
        System.out.println(System.identityHashCode(a));
        System.out.println(System.identityHashCode(b));

输出:

true
851664923
851664923

那么为什么你又感觉可变?

String a="test";
a="test1"

然后a就变成了test1,其实在这里是新建了一个"test1"字符串对象(如果常量池没有这个值的话就是新建)。然后将变量引用指向它。注意:这里并没有修改"test"这个变量的内部状态,"test"这个字符串对象是线程安全的。
除非你用final修饰,否则所有的变量指向都是可变的。
这种情况下要保证线程安全性:
第0:可以考虑使用volatile确保可见性。
第一可以使用final修饰
第二你可以使用AtomicReference之类的原子对象,对于Integer等也有AtomicInteger之类的
第三对相应代码区域加锁

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