L
Lee Fesperman
John said:The only question of variable scope that is relevant is whether a
variable is local (to a method) or not (in which case it is "shared").
Whether or not a shared variable is referenced in the synchronized
section does not affect the fact that the thread needs to reload it from
main memory the next time its value is used after the barrier, whether
that happens to occur inside the synchronized section or not. This can
result in the thread "seeing" a different value for *any* shared
variable after the barrier than it did before the barrier.
Yes, only "shared" variables need be considered. I was making a distinction between
shared variables that are accessed within the synchronized section and those that are
not. To clarify, "synchronized section" refers to *any* code synchronized by a specific
object reference. It is that distinction between shared variables that I am referring
to.
I understand that the definition of the memory barrier makes no such distinction between
shared variables. My point is that section of the JLS, as should other sections, should
be read as a conceptual description ... an "as if" description. Properly written code
should not depend on this being explicitly true, for the reasons I described below.
Yes, but more to the point, it is also incorrect to assume that the
synchronization *does not* affect any particular shared variable.
That's why the compiler cannot remove it, and why it's non-trivial for
the JIT to remove it.
Obviously, I disagree with your assertion that it would be incorrect (for JIT) to assume
that synchronization does not affect "unreferenced" shared variables. Any user code that
depends on this would be improper ... you seem to agree with that assertion. Given that
agreement, why would you object to a JIT optimizing that situation?
Multi-threaded programming *is* nondeterministic. The point of
synchronization is to constrain the possible global sequence of events,
but you cannot make it totally deterministic and retain "simultaneous"
execution. Chapter 17 of the JLS (second edition) is entirely devoted
to this topic.
Proper multithreading is not nondeterministic where it matters. Optimal multithreading
is concerned with constraining local sequences of events. Constraining global sequences
is sub-optimal.
That would not be sufficient to comply with the language's requirements.
The JIT conceivably could perform an analysis proving that it could
remove the barrier, but it would be considerably more complicated than
you suggest, as it would involve visibility and use analysis for all
variables visible to the thread at the barrier, relative to *all other
live threads*.
Lee, you seem to have some ideas about synchronization that are
inconsistent with the Java specs (or perhaps I'm totally wrong, but
either way ...), I suggest you read over JLS(2e).17 to see whether you
think it supports your position.
Ok, John. I will try to find the time to check that section of the JLS. However, I do
believe many areas of the JLS do need to be read as 'conceptual' in nature rather than
as absolute rules ... that a JIT following the spirit of the rules is sufficient.
I will also check with an associate who is developing a super, high-performance JVM for
his opinion on the matter.
This reminds me of a discussion I had with Dale King (funny that you are both from
Indiana) on this forum about a JIT aggressively reducing the reachability of references
within a method even though conceptually the reference was reachable until the end of
the method. This also conflicted with an explicit interpretation of the JLS, but I felt
this type of aggressive optimization was correct, even required. My aforementioned JVM
colleague agreed with me.
I do urge you to keep an open mind about this discussion. Others haven't ;^)