我已经读过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();
  }
}

10-07 19:42
查看更多