java - String是线程安全的吗?那String岂不是不能进行同步?
怪我咯
怪我咯 2017-04-18 10:27:08
0
2
612
  1. 我们知道不变对象是指一旦创建不能修改内部状态的对象,因为不变对象没有提供可供修改内部状态的方法,所以不变对象是线程安全的。但是String,当然包括其他的基本数据的包装类,如Integer/Long/Float等等,也是不变对象,但却是可以修改值的,这怎么保证线程安全?

public class Test{

private String str;

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

}

怪我咯
怪我咯

走同样的路,发现不同的人生

全部回覆(2)
Peter_Zhu

重新找可以鎖住的對象,鎖住它再修改String。

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

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之類的
第三對相應代碼區域加鎖

熱門教學
更多>
最新下載
更多>
網站特效
網站源碼
網站素材
前端模板
關於我們 免責聲明 Sitemap
PHP中文網:公益線上PHP培訓,幫助PHP學習者快速成長!