I don't understand how the JMM qualifies the usage of local variables inside lambdas (and also in local and anonymous classes).
It looks like they aren't "shared variables" in terms of the JLS:
Local variables (§14.4), formal method parameters (§8.4.1), and exception handler parameters (§14.20) are never shared between threads and are unaffected by the memory model.
But what are they then?
For example, could the following code print 0
?
public class Test1 {
static Runnable r = null;
public static void main(String[] args) throws Exception {
var t = new Thread(Test1::thread1);
t.start();
r = createLambda();
t.join();
}
static void thread1() {
Runnable localR;
while((localR = r) == null) {
Thread.onSpinWait();
}
localR.run();
}
static Runnable createLambda() {
var i = 10;
return () -> {
System.out.println(i); // could it print 0?
};
}
}
As far as I understand, if i
inside createLambda()
was a shared variable, then 0
could be printed (a default value for int
variable) because there is no happens-before between var i = 10;
in main()
thread and System.out.println(i)
in thread1()
thread.
But if i
is not a shared variable, then I don't know what is possible here.
!(UPDATE for moderators) I don't think this question is a duplicate of that question.
I guess you marked this question as a duplicate because you think that the answer to that question answers my question as well (because the texts of the questions differ significantly).
But it doesn't: the main thing that the answer misses is proofs (i.e. links to and citations from the specs, the javadocs etc.). Without official proofs the generated classes with final fields described in the answer could be just an internal detail of the current implementation, which could change at any time.
And actually it would be much better if there were proofs at the level of the Java language: that's because both the JMM (which I specifically asking about) and lambdas are defined at the language level (here and here), but the answer describes the level of the JVM - this is kind of weird when in order to find out how the two parts of the JLS are related to each other we have to read the (lower-level) JVM standard.
UPDATE (08 May 2023) User Holger in the comments provided the link to this answer, which answers this question.