Your statement that you are asking your question about:
At the moment that the MultiThreadingClass is initializing with its
constructor, it could happen that the File constructor on line 6 may
not see the value of myPath.
The answer is complicated.
You don't need to worry about the char-array value
inside the String
object. As I mentioned in the comments, because it is a final
field that is assigned in the constructors, and because String
doesn't pass a reference to itself before assigning the final
field, it is always safely published. You don't need to worry about the hash
and hash32
fields either. They're not safely published, but they can only have the value 0 or the valid hash code. If they're still 0, the method String.hashCode
will recalculate the value - it only leads to other threads recalculating the hashCode when this was already done earlier in a different thread.
The reference myPath
in MultiThreadingClass
is not safely published, because it is not final
. "At the moment that the MultiThreadingClass is initializing with its constructor", but also later, after the constructor completed, other Threads than the thread that ran the constructor may see the value null
in myPath
rather than a reference to your string.
There's an example in the Java Memory Model section of the Java Language Specification [version 8 linked but this is unchanged since JMM was released in JSR-133]:
Example 17.5-1. final Fields In The Java Memory Model
The program below illustrates how final fields compare to normal fields.
class FinalFieldExample {
final int x;
int y;
static FinalFieldExample f;
public FinalFieldExample() {
x = 3;
y = 4;
}
static void writer() {
f = new FinalFieldExample();
}
static void reader() {
if (f != null) {
int i = f.x; // guaranteed to see 3
int j = f.y; // could see 0
}
}
}
The class FinalFieldExample has a final int field x and a non-final
int field y. One thread might execute the method writer and another
might execute the method reader.
Because the writer method writes f after the object's constructor
finishes, the reader method will be guaranteed to see the properly
initialized value for f.x: it will read the value 3. However, f.y is
not final; the reader method is therefore not guaranteed to see the
value 4 for it.
This is even likely to happen on a heavily loaded machine with many threads.
Workarounds/solutions:
- Make
myPath
a final
field (and don't add constructors that pass out the this
reference before assigning the field)
- Make
myPath
a volatile
field
- Make sure that all threads accessing
myPath
synchronize on the same monitor object before accessing myPath
. For example, by making beginmt
a synchronized
method, or by any other means.