我已经读过Java String类是不可变的并且是线程安全的,但是对于Strings的引用分配是否是线程安全的,我仍然感到困惑。
第一个问题:如果线程A调用Foo.setString()
而线程B调用Foo.getString()
,则以下代码是线程安全的吗?
Class Foo {
String aString;
public String getString() {
return aString;
}
public void setString(s) {
aString = s;
}
}
第二个问题:如果以上代码不是线程安全的,请使用ReentrantLock,如何编写
Foo.getString()
方法?Class Foo {
String aString;
ReentrantLock aLock;
public String getString() {
aLock.lock();
return aString;
aLock.unlock(); // This line will be unreachable. How to fix??
}
public void setString(s) {
aLock.lock();
aString = s;
aLock.unlock();
}
}
我必须使用ReentrantLock,因为我需要使用tryLock(timeout)功能。
最佳答案
问题1:
这取决于您所说的线程安全的含义,Eric Lippert wrote a very good blog post about it here ...
但是将aString声明为volatile将意味着可以保证对不同线程的所有读取都是正确的。
问题2:
使用try ... finally构造,在finally块中解锁,例如:
public String getString() {
try {
aLock.lock();
return aString;
} finally {
aLock.unlock();
}
}
public void setString(s) {
try {
aLock.lock();
aString = s;
} finally {
aLock.unlock();
}
}