Jon Martin Solaas said:
That was all very blurry to me. But I'm no synchronization wizard. Would
you care to explain in detail what would be the difference if all the
synchronization blocks in the code in this news-thread (not execution
thread
were removed? Exactly what's the difference between
scanning=false;
and
synchronized (this) {
scanning=false;
}
?
The difference is that with the first, there's no guarantee at all as to
when another thread that reads 'scanning' will see its value as false.
With the latter, any thread that enters a synchronization block on the
object first and THEN reads 'scanning' is guaranteed to see its value as
being false.
This is not an easy thing to understand, unfortunately. The chapter of
the JLS that explains it is one of the most difficult in the whole book
(perhaps not quite so bad as the part about type inference for generic
method invocations without explicit type arguments). In essence,
though, when evaluating multithreading correctness you should stop
thinking in terms of a variable having only one value. It may have a
different value from the perspective of any thread; and it may have any
number of values, of which the variable may evaluate to any of them,
arbitrarily, when used as a value. The only way to avoid this is to use
the volatile or synchronized keywords. In this case, volatile would
have been sufficient. However, synchronized works as well.
What synchronized does is to establish a "happens-before" relationship.
That simply means that one action of the code is guaranteed to have
happened before another, and the results of the first statement are
therefore visible to the second. Entering or leaving a synchronized
block establishes such a "happens-before" relationship with another
thread that enters or leaves that same block. Therefore, the values
written to variables from the first thread are visible to the second.
Without the synchronization actions, there would be no such
relationships and it would be entirely possible for the second thread to
continue to read whatever value 'scanning' had when the thread was
started. (Because thread creation DOES establish such a "happens-
before" relatonship, it would not be possible for the second thread to
read a value of scanning from some time before the thread creation.)
What kind of happens-before-relationships are present in the latter, but
not in the first part here (or in the posted code if this example is to
simple)?
The original code without the synchronized statements establishes only
one significant happens-before relationship: namely, that the call to
thread.start() happens-before the first action of the new thread. There
are a HUGE number of other such relationships, due to the fact that
within a single thread each action of code happens-before any action of
code that comes after it; either in order of operations within an
expression, or in a subsequent statement. However, it's easier to not
mention those until they are needed, considering them obvious.
The code with the synchronized statement establishes those happens-
before relationships, plus additional happens-before relationships that
say that one thread exiting a synchronized block happens-before another
thread entering that block. These additional relationships are neeeded
to guarantee that changes to the 'scanning' variable made from run()
(and perhaps from Scan() if it's not called from the graphics thread)
are visible inside of paint(Graphics).
Does that help, or confuse you more?
--
www.designacourse.com
The Easiest Way To Train Anyone... Anywhere.
Chris Smith - Lead Software Developer/Technical Trainer
MindIQ Corporation