Behnil Behnil - 3 months ago 12
Java Question

Thread safety of final field

Let's say I have a JavaBean User that's updated from another thread like this:

public class A {

private final User user;

public A(User user) {
this.user = user;
}

public void aMethod() {
Thread thread = new Thread(new Runnable() {

@Override
public void run() {
...a long running task..
user.setSomething(something);
}

});
t.start();
t.join();
}

public void anotherMethod() {
GUIHandler.showOnGuiSomehow(user);
}
}


Is this code thread safe? I mean, when the thread that created A instance and called A.aMethod reads user fields, does it see user in the fresh state? How to do it in appropriate thread safe manner?

Note that I can't modify the user class and I don't know if it's thread safe itself.

Answer

Is this code thread safe? ... does it see user in the fresh state?

Not especially - the fact that user is final in your code makes almost no difference to thread safety other than the fact that it cannot be replaced.

The bit that should change is the instance variable that is set by setSomething. It should be marked as volatile.

class User {
  // Marked `volatile` to ensure all writes are visible to other threads.
  volatile String something;

  public void setSomething(String something) {
    this.something = something;
  }

}

If however (as you suggest) you do not have access to the User class, you must then perform a synchronization that creates a memory barrier. In its simplest form you could surround your access to the user with a synchronized access.

synchronized (user) {
  user.setSomething(something);
}

Added :- It turns out (see here) that this can actually be done like this:

volatile int barrier = 0;
...
user.setSomething(something);
// Forces **all** cached variable to be flushed.
barrier += 1;
Comments