From owner-java@jp.FreeBSD.org Wed Jul 24 19:28:54 2002
Received: (from daemon@localhost)
	by castle.jp.FreeBSD.org (8.11.6+3.4W/8.11.3) id g6OASsI28252;
	Wed, 24 Jul 2002 19:28:54 +0900 (JST)
	(envelope-from owner-java@jp.FreeBSD.org)
Received: from ongs.co.jp (ns.ongs.co.jp [202.216.232.58])
	by castle.jp.FreeBSD.org (8.11.6+3.4W/8.11.3) with SMTP/inet id g6OASrn28247
	for <java@jp.FreeBSD.org>; Wed, 24 Jul 2002 19:28:53 +0900 (JST)
	(envelope-from daichi@ongs.co.jp)
Received: (qmail 62509 invoked from network); 24 Jul 2002 10:24:48 -0000
Received: from unknown (HELO parancell.ongs.co.jp) (202.216.232.62)
  by ns.ongs.co.jp with SMTP; 24 Jul 2002 10:24:48 -0000
Date: Wed, 24 Jul 2002 19:23:25 +0900
From: daichi <daichi@ongs.co.jp>
To: java@jp.FreeBSD.org
Message-Id: <20020724192325.55472fab.daichi@ongs.co.jp>
In-Reply-To: <20020724.012519.74758165.yamasa@ec.catv.ne.jp>
References: <20020719163614.7ec433a8.daichi@jp.freebsd.org>
	<20020722.024117.74758272.yamasa@ec.catv.ne.jp>
	<20020722122116.218d7c4a.daichi@jp.freebsd.org>
	<20020724.012519.74758165.yamasa@ec.catv.ne.jp>
Organization: ONGS Inc.
X-Mailer: Sylpheed version 0.8.0 (GTK+ 1.2.10; i386-portbld-freebsd4.6)
Mime-Version: 1.0
Content-Type: text/plain; charset=ISO-2022-JP
Content-Transfer-Encoding: 7bit
Reply-To: java@jp.FreeBSD.org
Precedence: list
X-Sequence: java 138
Subject: [java 138] Re: Java Memory Model
Errors-To: owner-java@jp.FreeBSD.org
Sender: owner-java@jp.FreeBSD.org
X-Originator: daichi@ongs.co.jp
X-Distribute: distribute version 2.1 (Alpha) patchlevel 24e+020717

$BBgCO$G$9!#(B

$BBg@P$5$s$4;XF3$"$j$,$H$&$4$6$$$^$9!#$b$&0l2s(B
The "Double-Checked Locking is Broken" Declaration
http://www.cs.umd.edu/~pugh/java/memoryModel/DoubleCheckedLocking.html
$B$rFI$s$G!"MW;]$r$^$H$a$F$_$^$7$?!#$3$s$J46$8$G$"$C$F$^$9$G$7$g$&$+!#(B

 $B!Z(BDCL(Double-Checked Locking) $B$H$O![(B
  synchronized$B%V%m%C%/$K$h$kF14|$r:G=i$N%*%V%8%'%/%H$N@8@.;~(B
  $B$N$_$K$J$k$h$&$K(Bsynchronized$B%V%m%C%/$rH=DjJ8$G$/$/$k$J$I$r(B
  $B9T$&%^%k%A%9%l%C%I4D6-$K$*$1$kCY1d=i4|2=J}K!!#(B
  ($B4|BTDL$j$KF0$/$N$G$"$l$P(B)$B%*%V%8%'%/%H$NCY1d@8@.$rJ#?t$N%9(B
  $B%l%C%I$,F0:n$7$F$$$F$b=EJ#$J$/3N<B$K9T$&$3$H$,$G$-!"$=$NF1(B
  $B4|;~4V$r:G=i$N@8@.;~$N$_$K2!$5$($k$3$H$,$G$-$k(B

 $B!Z(BDCL$B$NLdBjE@![(B
  DCL$B$O<B9T$9$k4D6-$dJ}K!$K$h$C$F@5$7$/F0:n$9$k>l9g$H$=$&$G(B
  $B$J$$>l9g$,$"$k!#(BJava$B$G$O4|BTF0$+$J$$$3$H$,$"$k!#(B

 $B!Z(BJava$B$K$*$1$k(BDCL$B$NF0:n![(B
  Java$B$G$O(BDCL$B$,@5$7$/F0:n$7$J$$!#<gMW$?$kFs$D$NM}M3$O2<5-$N(B
  $BDL$j$G$"$k!#(B

    1. $B!V%*%V%8%'%/%H$N=i4|2=!W$H!V%U%#!<%k%I$X$N=q$-9~$_!W(B
       $B$N4V$K=g=x5,B'$,$J$$!#%3%s%Q%$%i$,$3$l$i=g=x$r5UE>(B
       $B$5$;$k$3$H$O@5Ev$G$"$k!#%3%s%Q%$%i$,$3$l$i=hM}$r5U(B
       $B$K$9$k$H(BDCL$B$O@5$7$/F0:n$7$J$$2DG=@-$,$"$k!#(B
       # $B8e=R$7$^$9$,$3$NItJ,$,M}2r$G$-$:(B

    2. monitorexit($B;2>H$KBP1~$7$?%b%K%?$r2rJ|$9$k%P%$%HL?Na(B)
       $B$K4X$9$k5,B'$K5/0x$9$kM}M3$,$"$k!#(Bmonitorexit$B$NA0$N(B
       $B=hM}$O%b%K%?$,2rJ|$5$l$kA0$K<B9T$5$l$J$1$l$P$J$i$J$$(B
       $B$H$$$&5,B'$,$"$k$,!"(Bmonitorexit$B$h$j8e$N=hM}$,%b%K%?$,(B
       $B2rJ|$5$l$kA0$K$5$l$F$$$O$$$1$J$$$H$$$&5,B'$O$J$$!#(B
       $B0lJ}J}8~$J%a%b%jJ]8nL?Na$r;}$C$F$$$k%W%m%;%C%5$G$O(B
       synchronized$B%V%m%C%/Fb$K(Bsynchronized$B%V%m%C%/$,$"$k>l(B
       $B9g!"=hM}$r$9$Y$F0l$D$N(Bsynchronized$B%V%m%C%/$XA0E]$7(B
       $B$=$NL?Na$rMxMQ$9$k$3$H$,@-G=$N8~>e$K$D$J$,$k!#$h$C$F(B
       $B$=$N$h$&$K=hM}$5$l$k$3$H$O$*<j:"$G@5Ev$J=hM}$G$"$k!#(B
       $B$3$N$?$a!"(Bsynchronized$B%V%m%C%/Fb$K(Bsynchronized$B%V%m%C%/(B
       $B$r@_$1$F=hM}$rF14|$5$;$h$&$H$$$&;n$_$O!"7k6I(B1.$B$HF1$8(B
       $B>u67$K$J$k$?$a0UL#$,$J$$!#(B

 $B!Z(BJava$B$K$*$1$k(BDCL$B$X$NBP1~=hCV![(B

    1. DCL$B$rMxMQ$7$J$$!#(BDCL$B$rMxMQ$9$k%2%C%?!<%a%=%C%I$N%3%9(B
       $B%H$OHy!9$?$k$b$N$G$"$m$&!#%"%W%j%1!<%7%g%s$N@-G=Nt2=(B
       $B$,$3$N%a%=%C%I$K$+$+$C$F$$$k$o$1$G$J$$$N$J$i!"(BDCL$B$r(B
       $BMxMQ$7$J$$$GNI$$!#(B

    2. 32bit primitive value(int)$B$r(Bsynchronized$B%V%m%C%/$XF~$k(B
       $B$+F~$i$J$$$+$NH=Dj=hM}$KMxMQ$9$k!#(B32bit int$B$O=hM}$,(B
       atmic$B$G$"$k$3$H$,J]>Z$5$l$F$$$k!#$3$N$?$a;2>H$rMxMQ(B
       $B$7$FH=Dj$9$k>l9g$H0c$$(BDCL$B$OF0:n$9$k(B

    3. java.lang.ThreadLocal$B$rMxMQ$9$k!#(B

 $B!Z(BJava$B$K$*$1$k(BDCL$B$X$NBeBX$(0F![(B
    static$B$J%/%i%9JQ?t$O;2>H$,$"$k$^$G=i4|2=$5$l$J$$$N$G!"(B
    $B$3$l$r(BDCL$B$NBe$o$j$H$7$F$O$I$&$+!#(B

----

$B0UL#$,NI$/$o$+$i$J$$ItJ,$,$A$i$[$i$H!#(B

  It is perfectly reasonable and legal for the compiler to move 
  the assignment helper = h; inside the synchronized block, in 
  which case we are back where we were previously. Many processors 
  offer instructions that perform this kind of one-way memory 
  barrier. Changing the semantics to require releasing a lock to 
  be a full memory barrier would have performance penalties.

$B$3$NItJ,$O!V(Bone-way memory barrier $BL?Na!W$N$h$&$J$b$N$,8=:_$N(B
CPU$B$K$OMQ0U$5$l$F$$$F!"$3$l$rMxMQ$9$k$?$a$K7k6I(B

  synchronized(this) {
      synchronized(this) {
          synchronized(this) {
              synchronized(this) {
                  $B=hM}(BA;
              }
              $B=hM}(BB;
          }
          $B=hM}(BC;
      }
      $B=hM}(BD;
  }

$B$H$$$&$h$&$J%3!<%I$O(B

  synchronized(this) {
      synchronized(this) {
          synchronized(this) {
              synchronized(this) {
                  $B=hM}(BA;
                  $B=hM}(BB;
                  $B=hM}(BC;
                  $B=hM}(BD;
              }
          }
      }
  }

$B$KJQ$($i$l$F(B($B$7$+$b(Bmonitorexit$B$NA0$K=hM}$r;}$C$F$-$F$O$$$1$J(B
$B$$$H$$$&5,B'$O$J$$$N$G@5Ev$J=hM}(B)$B!"7k6I(B

  synchronized(this) {
      $B=hM}(BA;
      $B=hM}(BB;
      $B=hM}(BC;
      $B=hM}(BD;
  }

$B$KF1$8!"$H$$$&$3$H$G$7$g$&$+!#(B

$B$"$H!"4NItJ,$@$H;W$o$l$k$3$3$N$H$3$m$,(B

  The most obvious reason it doesn't work it that the writes that 
  initialize the Helper object and the write to the helper field 
  can be done or perceived out of order. Thus, a thread which 
  invokes getHelper() could see a non-null reference to a helper 
  object, but see the default values for fields of the helper 
  object, rather than the values set in the constructor. 

  If the compiler inlines the call to the constructor, then the 
  writes that initialize the object and the write to the helper 
  field can be freely reordered if the compiler can prove that 
  the constructor cannot throw an exception or perform synchronization.

  Even if the compiler does not reorder those writes, on a 
  multiprocessor the processor or the memory system may reorder 
  those writes, as perceived by a thread running on another processor. 

$B$h$/$o$+$i$J$/$F!#(B

  class Foo { 
    private Helper helper = null;
    public Helper getHelper() {
      if (helper == null) 
        synchronized(this) {
          if (helper == null) 
            helper = new Helper();
        }    
      return helper;
      }
    // other functions and members...
    }

$B$O!"$D$^$j(B

            helper = new Helper();

$B$NItJ,$,(Batomic$B$8$c$J$$$s$G$9$h$M(B($B$3$N9M$($,0c$C$F$$$k$N$+$J$!(B)$B!#(B
$B$G$b(B

  The rule for a monitorexit (i.e., releasing synchronization) is that 
  actions before the monitorexit must be performed before the monitor is 
  released. However, there is no rule which says that actions after the 
  monitorexit may not be done before the monitor is released.

$B$H$"$k$N$G!"%b%K%?$,2rJ|$5$l$kA0$K(Bhelper$B$K$OCM$,BeF~$5$l$k$s$8$c(B
$B$J$$$+$H;W$C$F!#$=$&$9$k$H(B

  The most obvious reason it doesn't work it that the writes that initialize 
  the Helper object and the write to the helper field can be done or 
  perceived out of order. Thus, a thread which invokes getHelper() could see 
  a non-null reference to a helper object, but see the default values for 
  fields of the helper object, rather than the values set in the constructor. 

$B$J$s$G$3$&=q$$$F$$$k$N$@$m$&!"$H!#%*%V%8%'%/%H$N@8@.=hM}$O(Bmonitorexit
$B$NA0$K5-=R$5$l$F$$$F$b$=$N>l$G$O=*N;$7$J$$(B?
# $B1Q8l$NFI$_4V0c$$(B?

$B$"$H!"(BDCL$B$,F0:n$9$kNc$H$7$F>R2p$5$l$F$$$k(BThreadLocal$B$rMxMQ$9$kNc$O(B
$B7k6IA0=R$7$?%3!<%I$H2?$,0c$&$N$+0c$$$,$o$+$i$:!#(B

The most obvious reason it doesn't work...$B$NItJ,$O!V(BSynchronization and the 
Java Memory Model$B!W$rFI$`$HFf$,@b$1$=$&$J$N$G!"$3$l$+$i$3$C$AFI$_$^$9!#(B

--
Daichi GOTO
    http://www.ongs.net/daichi, daichi@jp.freebsd.org
