您正在阅读字符串是线程安全的,因为它是不可变的。
例如我做:
String a = "test";
一个线程使用此变量。 但另一个线程仍然可以使用此变量并更改它:
a = a + "something";
所以它会改变吗?
如果它是易失性的,我会得到它,它一次只能被一个线程使用。但不可靠性并不能保证我这个!?
答案 0 :(得分:5)
您没有更改a
指向的对象,但a
指向的位置:
String a = "test";
此处a
指向字符串"test"
a = a + "something";
这里创建了一个新字符串,作为"test"
和"something"
串联的结果,"testsomething"
指向的地方。a
这是一个不同的例子。
因此没有线程安全的问题,因为两个线程都有自己的"test"
引用相同的"testsomething"
字符串对象,但是一旦其中一个线程将修改字符串引用"test"
对象,另一个线程仍将引用原始{{1}}对象。
答案 1 :(得分:2)
字符串本身没有改变,引用是。听起来你需要参考是最终的。不变性保证了对象不会改变,而不是参考不能改变。只需将其标记为:
final String a = "test";
答案 2 :(得分:0)
通过让每个线程复制引用a
,您可以轻松地使代码线程安全。事实上,这通常是发生的事情,因为你通常通过参数将字符串传递给线程。
因此两个线程都持有对原始字符串的引用,此处为"test"
。如果线程1现在修改a
,它只会修改此引用。线程2仍然保留对"test"
的完整引用,因为字符串本身(而不是引用)是不可变的。
答案 3 :(得分:0)
字符串对象是线程安全的。如果您的String a
是局部变量,那么此代码仍然是线程安全的。如果它是您班级的一个领域,那么您有责任保证其线程安全。 String的线程安全性不会神奇地使您自己的代码线程安全。你应该好好照顾它。
您可以使字段变为volatile,然后在线程中获得可见性。因此,任何线程都会看到您的字段的最新值。但是你不会以这种方式获得原子性。想象一下以下内容。让a = "test"
。线程1更新a和线程2更新a。他们都看到当前值"test"
。他们读取它,通过连接创建新字符串并更新a
的值。这个价值会是什么?这是未知的。如果线程严格依次执行其操作,则可以是"testsomethingsomething"
。但它可能只是"testsomething"
。例如:
"test"
a
"test"
a
a
"testsomething"
a
a
(请记住,之前"test"
为"testsomething"
)
Voila,你已经失去了对你的领域的更新。为避免此类问题,您应该使用单个锁定对象上的同步来保护对字段的所有访问和修改。
答案 4 :(得分:0)
这里有很多困惑......
某些类的线程安全性意味着并发使用它的实例 不会破坏它的内部结构。
在我们的案例中,我们终于得到了一个" testsomething"这只是保修,但不是像 " tsomethingest"或" tesomethingst"或" tseosmtething"或者"测试的东西"。
这里有一个快速而又脏兮兮的"插图:
public class Test2 {
private volatile String tstStr = "";
Test2(){
}
void impl(int par){
Thread wrk = new Thread(new MyRun(par));
wrk.start();
}
static public void main(String[] args) throws Exception {
Test2 tst2 = new Test2();
long startTime = System.currentTimeMillis();
Thread wrk;
for (int i = 0; i < 9; i=i+1) {
tst2.impl(i);
}
long endTime = System.currentTimeMillis();
System.out.println("The process took " + (endTime - startTime) + " milliseconds");
}
class MyRun implements Runnable {
int no;
MyRun(int var){
no = var;
}
public void run(){
tstStr = tstStr + " " + no;
for (int i = 0; i < 3; i=i+1) {
System.out.println("Message from "+no+", tested string ="+tstStr);
}
}
}
}
输出:
Message from 1, tested string = 0
Message from 1, tested string = 0 2 3
Message from 1, tested string = 0 2 3
Message from 4, tested string = 0 2 3 4
Message from 4, tested string = 0 2 3 4
Message from 0, tested string = 0 2
Message from 8, tested string = 0 2 3 4 7 8
Message from 5, tested string = 0 2 3 4 7 8 5
Message from 0, tested string = 0 2 3 4 7 8 5
Message from 0, tested string = 0 2 3 4 7 8 5
The process took 0 milliseconds
Message from 7, tested string = 0 2 3 4 7
Message from 7, tested string = 0 2 3 4 7 8 5 6
Message from 4, tested string = 0 2 3 4
Message from 3, tested string = 0 2 3
Message from 2, tested string = 0 2
Message from 3, tested string = 0 2 3 4 7 8 5 6
Message from 7, tested string = 0 2 3 4 7 8 5 6
Message from 6, tested string = 0 2 3 4 7 8 5 6
Message from 5, tested string = 0 2 3 4 7 8 5
Message from 8, tested string = 0 2 3 4 7 8 5
Message from 5, tested string = 0 2 3 4 7 8 5 6
Message from 6, tested string = 0 2 3 4 7 8 5 6
Message from 3, tested string = 0 2 3 4 7 8 5 6
Message from 2, tested string = 0 2 3 4 7 8 5 6
Message from 6, tested string = 0 2 3 4 7 8 5 6
Message from 8, tested string = 0 2 3 4 7 8 5 6
Message from 2, tested string = 0 2 3 4 7 8 5 6