我们知道不变对象是指一旦创建不能修改内部状态的对象,因为不变对象没有提供可供修改内部状态的方法,所以不变对象是线程安全的。但是String,当然包括其他的基本数据的包装类,如Integer/Long/Float等等,也是不变对象,但却是可以修改值的,这怎么保证线程安全?
public class Test{
private String str;
public void test(){
if(("").equals(str)){ //多个线程同时判断,可能导致多次执行
str = "1";
//do something
}
}
}
ロックできる別のオブジェクトを見つけてロックし、文字列を変更します。
リーリーJava では、String 型オブジェクト自体は不変です。 String は定数プールと呼ばれるメモリ領域に格納されるためです。
リーリー例えば
出力:
リーリーそれでは、なぜまた変化を感じるのですか?
リーリーその後、 a は test1 になります。実際、ここで新しい「test1」文字列オブジェクトが作成されます (定数プールにこの値がない場合は、新しく作成されます)。次に、変数参照をそれを指します。注: ここでは、「test」変数の内部状態は変更されません。「test」文字列オブジェクトはスレッドセーフです。
final で変更しない限り、指す変数はすべて変更可能です。
この場合、スレッドの安全性を確保する必要があります:
いいえ 0: 可視性を確保するために volatile の使用を検討できます。
第一に、最終的な変更を使用できます
第二に、AtomicReferenceなどのアトミックオブジェクトを使用でき、Integerの場合はAtomicIntegerなどもあります
第三に、対応するコード領域をロックします