3

Basically the following works but since I read about the final keyword I am not sure anymore if I have to declare name final if different threads access it?

Thanks in advance.

public class Test4 {

    // to ensure thread-safety do we have to declare the variable name final ?
    private String name;

    public Test4 (String name) {
        this.name = name;
    }

    public void start() {
        new MyThread().start();
    }

    private class MyThread extends Thread {

        public void run() {
            System.out.println(name);
        }
    }

    public static void main(String[] args) {
        Test4 t = new Test4("Don't know if I am threadsafe");
        t.start();
    }

}
  • this will always print "Don't know if I am threadsafe", regardless of final. Until the object is constructed, the new() will not return; this will happen before the new thread is started. – tucuxi Jan 16 '13 at 10:06
  • @pst in the event of further writes to `name`, yes, there are differences. However, if the only time `name` is written is during construction, then `final` is never required (though it does make the intent clearer to readers). – tucuxi Jan 16 '13 at 10:12

6 Answers6

4

The final modifier - while preventing the member from being re-assigned - does not affect the correctness of the given code1

From the the 17.4.4 Synchronization Order section for the Java 5 Language Specification:

A synchronization order is a total order over all of the synchronization actions of an execution .. Synchronization actions induce the synchronized-with relation on actions, defined as follows:

  • ..
  • An action that starts a thread synchronizes-with the first action in the thread it starts.
  • ..

Then, since the thread that sets the name member is the one that starts the thread, the synchronization order is guaranteed. (Synchronizes-with implies a Happens-before ordering.)

Note that:

  • The member name needs only be set before starting the thread: that is, it does not need to be set in the constructor for this synchronizes-with guarantee.
  • This does not guarantee synchronization ordering - and thus it does not guarantee happens-before or value visibility - between already running threads or threads created elsewhere!

However, final fields do give a much more comfortable feeling (ref. 17.5 Final Field Semantics):

An object is considered to be completely initialized when its constructor finishes. A thread that can only see a reference to an object *after that object has been completely initialized is guaranteed to see the correctly initialized values for that object's final fields.

In this case, with final fields, the value is guaranteed to be visible on every thread after the constructor completes. (This guarantee can be violated by "constructor leaks".)


1 In the supplied code the "non-final" name member is only assigned once before the thread is started.

In different, less trivial, programs other synchronization issues may be exposed. This answer examines if removing final alters the correctness of the supplied code.

All that being said, I consider it "good practice" to use both immutable variables (final) and immutable objects - especially when dealing with threads. Instead of needing to know the little arcane details of the JVM, do the safe proven things and strive for obvious correctness over cleverness or "performance".

See also:

Community
  • 1
  • 1
  • Overly-complicated answer (noting that the object's start() method is called only after building it, and therefore will see the fully-built state, would have sufficed), but correct and complete. – tucuxi Jan 16 '13 at 10:30
3

final variables are immutable, you can not change the value once it is constructed so it does not have concurrency issue.

Subhrajyoti Majumder
  • 40,646
  • 13
  • 77
  • 103
  • While true, final variables that evaluate to mutable Objects can end up in a world of odd behaviors .. so in this case it's true because the *variable is final* and the *String object is immutable*. (However though, to answer the question of if it is thread-safe requires knowing the happens-before of non-static final *member* fields, and I'm not entirely certain that final - or lack thereof - actually changes this behavior.) –  Jan 16 '13 at 09:22
  • So `final` does indeed do something wrt constructors and threading (see [Final Field Semantics](http://docs.oracle.com/javase/specs/jls/se5.0/html/memory.html#66562)); this is through guaranteed JVM semantics though, and *not* just "because it can't be reassigned". –  Jan 16 '13 at 09:45
  • Thanks for the Semantics and I do agree on "usage model" of final variable's complete initialization. – Subhrajyoti Majumder Jan 16 '13 at 10:08
2

You will not get the correct value of the field without final.

Maybe the thread got the old value after you changing the value of field.

Check the Visibility of JMM.

Another link of volatile.

Happends-Before Rule.

Happends-Before in JMM.

imxylz
  • 7,847
  • 4
  • 28
  • 25
  • 1
    I do not believe this is correct. That is, doesn't *starting* the thread cause a "happens before" in this case? (Although I cannot find supporting information at the moment.) –  Jan 16 '13 at 09:13
  • Ah, I think here: http://stackoverflow.com/questions/7651226/java-happend-before-thread-start (but I may be reading wrong) –  Jan 16 '13 at 09:19
1

Could you be looking for an AtomicReference or perhaps volatile? It depends what you mean by thread safe?

// Atomic to allow deeper control of updates.
private AtomicReference<String> name = new AtomicReference<String>();
// Volatile to ensure it is not cached.
private volatile String vName;

public Test(String name) {
  this.name.set(name);
  this.vName = name;
}

public void start() {
  new MyThread().start();
}

private class MyThread extends Thread {
  public void run() {
    System.out.println(name.get());
    System.out.println(vName);
  }
}
OldCurmudgeon
  • 64,482
  • 16
  • 119
  • 213
0

final doesn't have nothing with multithreading, but you should put final if your fild shouldn't be changed and is initialized in constructor of class. This means that fild can't be changed latter.

partlov
  • 13,789
  • 6
  • 63
  • 82
  • `final` does add multithreading guarantees, it seems; in this case the final field value is *guaranteed* to be visible (by other threads) after the constructor exists. –  Jan 16 '13 at 09:46
  • this guarantee would be unnoticeable, as the hypothetical other threads may or may not have finished executing the part that reads the `final` field by the time the constructor starts executing. So this particular race condition would still exist. – tucuxi Jan 16 '13 at 10:26
0

since String is immutable and you declare the field final ,with all threads accessing it after the field assignment, then surely there will be no concurrent issues since the field would be used only for Read operation,in contrast to the case where StringBuilder were used.

shaydel
  • 589
  • 4
  • 15