Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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.

like image 537
Jan Krakora Avatar asked May 23 '13 08:05

Jan Krakora


2 Answers

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;
like image 127
OldCurmudgeon Avatar answered Oct 08 '22 13:10

OldCurmudgeon


marking field as final just means that reference cannot be changed. It means nothing about thread safity of class User. If methods of this class that access fields are synchronized (or use other synchronization technique) it is thread safe. Otherwise it is not.

like image 26
AlexR Avatar answered Oct 08 '22 13:10

AlexR