On Fri, 15 Oct 1999, Peter Pilgrim wrote:
> In fact code is wrong, at least in the conditionals statements.
> Sorry about that
>
> public static NetworkPrinter getInstance()
> {
> // Point *A*
> if ( thePrinter == null ) {
> // Thread Safety - Double Guard technique
> // Point *B*
> synchronized( locker ) {
> // Point *C*
> // SHOULD BE A CRITICAL SECTION
> if ( thePrinter == null ) {
> thePrinter = new NetworkPrinter();
> }
> }
> return (thePrinter);
> }
>
> I can't understand what is the problem with the double guard technique.
> You synchronize threads on the `locker' object and that should be
> enough. In fact it should act like a `Mutex' (mutual exclusion).
You are not synchronizing threads on the locker object. If you
were doing that, you would have synchronization on the locker object
for each thread that tried to use thePrinter. You don't. Nothing
stops one thread from still being in the synchronized section while
another thread uses a partially stored result.
> If you have two threads t1 and t2 racing to create the singleton
> which is not yet inited yet at Point A, both will get to Point B.
> However only one of the two threads, assume by random choice t2,
> will get to Point C, because of the use of the synchronized object
> `locker'. Thread t2 will be allowed access to the critical section,
> and t1 will be blocked until t2 leaves the critical section.
> t2 will create the singleton and return it to its calling
> thread. As it leaves the monitor `locker' it will unblock t1
> from waiting, t1 will enter the critical section, and
> discovers that the singleton `thePrinter' already exists.
> It therefore returns the same singleton that t2 created.
>
> So converning invisiblity and visibility what's the problem?
Your mistake is in assuming that just because the thePrinter reference is
visible, everything that it references is visible, ie. the complete object
is visible. That is _not_ necessarily the case because Java does _not_
guarantee that all changes will be visible just because one is and because
you have no synchronization on the thread that sees the thePrinter
reference before entering the synchronized section.
The thePrinter reference is not everything you need to be able to see, you
have to be able to see the object itself as well.
You need to read chapter 17 of the JLS very carefully:
http://java.sun.com/docs/books/jls/html/17.doc.html#30206
It summarizes things as:
- Proper use of synchronization constructs will allow reliable
transmission of values or sets of values from one thread to
another through shared variables.
- When a thread uses the value of a variable, the value it
obtains is in fact a value stored into the variable by that
thread or by some other thread. This is true even if the program
does not contain code for proper synchronization. For example,
if two threads store references to different objects into the
same reference value, the variable will subsequently contain
a reference to one object or the other, not a reference to some
other object or a corrupted reference value. (There is a special
exception for long and double values; see 17.4.)
- In the absence of explicit synchronization, a Java implementation
is free to update the main memory in an order that may be
surprising. Therefore the programmer who prefers to avoid
surprises should use explicit synchronization.
"a Java implementation is free to update the main memory in an order that
may be surprising."
In another section where it describes the constraints for actions on
a variable by a thread, it states:
Provided that all the constraints above and below are obeyed, a
load or store action may be issued at any time by any thread on
any variable, at the whim of the implementation.
Section 17.8 goes on:
If a variable is not declared volatile, then the rules in the
previous sections are relaxed slightly to allow store actions to
occur earlier than would otherwise be permitted. The purpose of
this relaxation is to allow optimizing Java compilers to perform
certain kinds of code rearrangement that preserve the semantics of
properly synchronized programs but might be caught in the act of
performing memory actions out of order by programs that are not
properly synchronized.
See also section 17.11 for a sample program demonstrating the effects
of out of order writes.
(I'll be quiet now and won't be offtopic any more...)
----------------------------------------------------------------------
To UNSUBSCRIBE, email to [EMAIL PROTECTED]
with a subject of "unsubscribe". Trouble? Contact [EMAIL PROTECTED]