How to set/get string in Java safely?

Lee picture Lee · Nov 13, 2011 · Viewed 8.9k times · Source

I have read Java String class is immutable and thread-safe but I am still confused about whether the reference assignment for Strings is thread-safe or not.

First question: If thread A calls Foo.setString() while thread B calls Foo.getString(), is following code thread-safe?

Class Foo {
    String aString;
    public String getString() {
        return aString;
    }
    public void setString(s) {
        aString = s;
    }
}

Second question: If the above code is not thread-safe, using a ReentrantLock, how do I write the Foo.getString() method?

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();
    }
}

I have to use a ReentrantLock because I need to use the tryLock(timeout) feature.

Answer

Rich O'Kelly picture Rich O'Kelly · Nov 13, 2011

Question 1: It depends what you mean by thread safe, Eric Lippert wrote a very good blog post about it here... But declaring aString as volatile will mean that any reads on different threads are guaranteed to be correct.

Question 2:

Use a try... finally construct, unlocking in the finally block eg:

public String getString() {
  try {        
    aLock.lock();
    return aString;
  } finally {
    aLock.unlock();
  }
}

public void setString(s) {
  try {        
    aLock.lock();
    aString = s;
  } finally {
    aLock.unlock();
  }
}