javamemory$model$ - ut · memory$wall$ • 1980 – 1$cpu$operaon$~1$memory$access$operaon$ •...

Post on 03-Oct-2020

4 Views

Category:

Documents

0 Downloads

Preview:

Click to see full reader

TRANSCRIPT

Java  Memory  Model  

when  you  think  you  know  Java…  

If  programmers  don’t  know  what  their  code  is  doing,  programmers  won’t  be  able  to  know  what  their  code  is  doing  wrong.    

Requirements  for  Programming  Language  Memory  Models  Jeremy  Manson  and  William  Pugh    

 

Agenda  

•  Why  JMM?  •  JMM  properCes  – Atomicity  – Visibility  – Reordering  

•  VolaCle  •  Final  fields  

Memory  wall  

•  1980  – 1  CPU  operaCon  ~  1  memory  access  operaCon  

•  2010  – CPU  speed  increased  ~10000  Cmes  – Memory  speed  increased  ~10  Cmes  L  

•  2005  “The  Free  Lunch  Is  Over”  –  hVp://www.gotw.ca/publicaCons/concurrency-­‐ddj.htm    

Consequences  

•  Complex  architecture  of  the  modern  CPUs  – MulCcore  – Out-­‐of-­‐order  execuCon  – Store  buffers  – Hierarchical  caches  – Cache  coherence  protocols  – NUMA  

Java  Memory  Model  

•  Specifies  minimal  guarantees  given  by  JVM  

•  Key  principles:  – All  threads  share  the  main  memory  – Each  thread  uses  a  local  working  memory  – Flushing    or  refreshing  working  memory  to/from  main  memory  must  comply  to  JMM  rules  

T1   T2   T3  

working  memory  

working  memory  

working  memory  

main  memory  

 It  is  all  about  proper  

synchroniza9on!  

Safety  issues    in  mulCthreaded  systems  

•  Many  intuiCve  assumpCons  do  no  hold  •  Some  widely  used  idioms  do  not  hold  – Double-­‐checked  locking  idiom  – Checking  non-­‐volaCle  flag  for  thread  terminaCon  

•  Can’t  depend  on  tesCng  to  check  errors  – Some  anomaliCes  will  occur  only  on  some  plaforms  

– AnomaliCes  will  occur  randomly    

Taxonomy  

•  High  level  concurrency  abstracCons  –  java.uCl.concurrent  

•  Low  level  locking  – synchronized  blocks  &  java.uCl.concurrent.locks  

•  Low  level  primiCves  – volaCle,  java.uCl.concurrent.atomic  

•  Data  races:  deliberate  undersynchronizaCon  – Don’t  try  it  at  home!  

SynchronizaCon  is  needed    for  blocking  and  visibility  

•  SynchronizaCon  isn’t  just  about  mutual  exclusion  and  blocking  

•  It  also  regulates  when  other  threads  must  see  writes  by  other  threads  – When  writes  become  visible  

•  Without  synchronizaCon,  compiler  and  processor  are  allowed  to  reorder  memory  accesses  in  ways  that  may  surprise  you  – And  break  your  code  

x  =  y  =  0  

x  =  1  

j  =  y  

y  =  1  

i  =  x  

Thread  1   Thread  2  

Can  this  result  in  i=0  and  j=0?  

start  threads  

x  =  y  =  0  

x  =  1  

j  =  y  

y  =  1  

i  =  x  

Thread  1   Thread  2  

Can  this  result  in  i=0  and  j=0?  

start  threads  

x  =  y  =  0  

x  =  1  

j  =  y  

y  =  1  

i  =  x  

Thread  1   Thread  2  

Can  this  result  in  i=0  and  j=0?  

start  threads  

x  =  y  =  0  

x  =  1  

j  =  y  

i  =  x  

y  =  1  

Thread  1   Thread  2  

Can  this  result  in  i=0  and  j=0?  

start  threads  

x  =  y  =  0  

x  =  1  

j  =  y  

i  =  x  

y  =  1  

Thread  1   Thread  2  

Can  this  result  in  i=0  and  j=0?  

start  threads  

x  =  y  =  0  

x  =  1  

j  =  y  

i  =  x  

y  =  1  

Thread  1   Thread  2  

Can  this  result  in  i=0  and  j=0?  

start  threads  

x  =  y  =  0  

x  =  1  

j  =  y  

i  =  x  

y  =  1  

Thread  1   Thread  2  

Can  this  result  in  i=0  and  j=0?  

start  threads  

Yes!  

How  can  this  happen?  

•  Compiler  can  reorder  statements  – Or  keep  values  in  registers  

•  Processor  can  reorder  statements  •  On  mulC-­‐processor,  values  not  synchronized  to  global  memory  

•  The  memory  model  is  designed  to  allow  aggressive  opCmizaCon  

ref1.  x  =  1  

lock  M  

glo  =  ref1  

unlock  M  

When  are  acCons  visible    to  other  threads?  

lock  M  

ref2  =  glo  

unlock  M  

j  =  ref2.x  Thread  1  

Thread  2  

ref1.  x  =  1  

lock  M  

glo  =  ref1  

unlock  M  

When  are  acCons  visible    to  other  threads?  

lock  M  

ref2  =  glo  

unlock  M  

j  =  ref2.x  Thread  1  

Thread  2  Everything  before    

an  unlock  

ref1.  x  =  1  

lock  M  

glo  =  ref1  

unlock  M  

When  are  acCons  visible    to  other  threads?  

lock  M  

ref2  =  glo  

unlock  M  

j  =  ref2.x  Thread  1  

Thread  2  Everything  before    

an  unlock  

ref1.  x  =  1  

lock  M  

glo  =  ref1  

unlock  M  

When  are  acCons  visible    to  other  threads?  

lock  M  

ref2  =  glo  

unlock  M  

j  =  ref2.x  Thread  1  

Thread  2  Everything  before    

an  unlock  

Is  visible  to  everything  aHer  a  later  lock  on    the  same  Object  

ref1.  x  =  1  

lock  M  

glo  =  ref1  

unlock  M  

When  are  acCons  visible    to  other  threads?  

lock  M  

ref2  =  glo  

unlock  M  

j  =  ref2.x  Thread  1  

Thread  2  Everything  before    

an  unlock  

Is  visible  to  everything  aHer  a  later  lock  on    the  same  Object  

ref1.  x  =  1  

lock  M  

glo  =  ref1  

unlock  M  

When  are  acCons  visible    to  other  threads?  

lock  M  

ref2  =  glo  

unlock  M  

j  =  ref2.x  Thread  1  

Thread  2  Lock  release  &    subsequent  acquire  

Release  and  acquire  

•  All  memory  accesses  before  a  release  – Are  ordered  before  and  visible  to  any  memory  accesses  ajer  matching  acquire  

•  Unlocking  a  monitor/lock  is  a  release  – That  is  acquired  by  any  following  lock  of  that  monitor/lock  

…  

write(M1)  

…  

Visibility  between  threads  

…  

read(M1)  

…  Thread  1  

Thread  2  

…  

write(M1)  

…  

Visibility  between  threads  

…  

read(M1)  

…  Thread  1  

Thread  2  

Same  monitor!  

…  

write(V)  

…  

Visibility  between  threads  

…  

read(V)  

…  Thread  1  

Thread  2  V  -­‐  volaCle  

…  

write(V)  

…  

Visibility  between  threads  

…  

read(V)  

…  Thread  1  

Thread  2  

Same  variable!  

V  -­‐  volaCle  

Happens-­‐before  ordering  

   

A  release  and  a  matching  later  acquire    establish  a  happens-­‐before  relaConship  

 

•  Program  order  rule.  Each  acCon  in  a  thread  happens-­‐before  every  acCon  in  that  thread  that  comes  later  in  the  program  order.  (JLS  17.4.3)  

•  Monitor  lock  rule.  An  unlock  on  a  monitor  lock  happens-­‐before  every  subsequent  lock  on  that  same  monitor  lock.  (JLS  17.4.4)  

•  Vola9le  variable  rule.  A  write  to  a  volaCle  field  happens-­‐before  every  subsequent  read  of  that  same  field.  (JLS  17.4.5)  

•  Thread  start  rule.  A  call  to  Thread.start  on  a  thread  happens-­‐before  any  other  thread  detects  that  thread  has  terminated,  either  by  successfully  return  from  Thread.join  or  by  Thread.isAlive  returning  false.  

•  Interrup9on  rule.  A  thread  calling  interrupt  on  another  thread  happens-­‐before  the  interrupted  thread  detects  the  interrupt  (either  by  having  InterruptedExcepCon  thrown,  or  invoking  isInterrupted()  or  interrupted()).  (JLS  17.2.3)  

•  Finalizer  rule.  The  end  of  a  constructor  for  an  object  happens-­‐before  the  start  of  the  finalizer  for  that  object.  (JLS  17.4.5)  

•  Transi9vity.  If  A  happens-­‐before  B,  and  B  happens-­‐before  C,  then  A  happens-­‐before  C.  (JLS  17.4.5)  

Data  race  

•  If  there  are  two  accesses  to  memory  locaCon,  – At  least  one  of  those  is  a  write,  and  – The  memory  locaCon  is  not  vola5le,  then    

The  access  must  be  ordered  by  happens-­‐before    

int  a  =  o.field1;  synchronized  (o)  {        int  b  =  o.field1;        int  c  =  o.field2;        o.field3  =  b  +  c;  }  doStuff();  

//  Block  un9l  obtain  lock  //  get  main  memory  values  

//  commit  field3  to  main  memory  //  release  lock  

int  a  =  o.field1;  synchronized  (o)  {        int  b  =  o.field1;        int  c  =  o.field2;        o.field3  =  b  +  c;  }  doStuff();  

//  Block  un9l  obtain  lock  //  get  main  memory  values  

//  commit  field3  to  main  memory  //  release  lock  

•  Lock  coarsening:  it  is  allowed  to  take  accesses  outside  from  the  lock  region  and  move  ‘em  into  the  lock  region    

•  a.k.a  roach  motel  ordering:  can  move  accesses  in  but  cannot  move  ‘em  out  

Agenda  

•  Why  JMM?  •  JMM  properCes  – Atomicity  – Visibility  – Reordering  

•  Vola9le  •  Final  fields  

VolaCle  fields  

•  If  a  field  could  be  accessed  by  mulCple  threads,  and  at  least  one  of  those  is  a  write,  then:  – Use  locking  to  prevent  simultaneous  access,  or  – Make  the  field  vola9le  

volaCle  boolean  stop;  

What  does  volaCle  do?  

•  Reads  &  writes  go  directly  to  memory  – Caching  disabled  

•  VolaCle  longs  &  doubles  are  atomic  •  VolaCles  reads/writes  cannot  be  reordered  •  Reads/writes  become  acquire/release  pairs  

hVp://www.infoq.com/presentaCons/Do-­‐You-­‐Really-­‐Get-­‐Memory    Jevgeni  Kabanov.  Do  You  Really  Get  Memory  

Visibility:  thread  terminaCon    using  volaCle  field    

private  volaCle  boolean  stop  =  false;    

public  void  run()  {        while(!stop){              //  do  stuff  …        }  }    

public  void  stop(){        stop  =  true;  }    

stop  must  be  declared  volaCle,    otherwise,  compiler  could  keep  in  register  

Ordering:  transmixng  data    via  volaCle  field  

private  vola9le  boolean  ready;  private  Object  data;  public  Object  get()  {            if(!ready)  return  null;            return  data;  }   public  synchronized  void  set(Object  o)  {  

           if(ready)  throw…;              data  =  o;              ready  =  true;  }  

Ordering:  transmixng  data    via  volaCle  field  

private  vola9le  boolean  ready;  private  Object  data;  public  Object  get()  {            if(!ready)  return  null;            return  data;  }   public  synchronized  void  set(Object  o)  {  

           if(ready)  throw…;              data  =  o;              ready  =  true;  }  

Without  vola9le,    can  be    

reordered!  

VolaCle  arrays?  

•  volaCle  A[]  array;  •  volaCle  –  not  transiCve:  – …  =  array;                    //  volaCle  read  – array  =  …                      //  volaCle  write  – array[  i  ]  =…            //  normal  write  

•  java.uCl.concurrent:  – AtomicIntegerArray,  AtomicLongArray,  AtomicReferenceArray  

Agenda  

•  Why  JMM?  •  JMM  properCes  – Atomicity  – Visibility  – Reordering  

•  VolaCle  •  Final  fields  

Special  semanCcs  of  final  fields    

class  A  {      final  B  ref;      public  A  (…)  {            this.ref  =  …  ;      }  }  

Once  constructor  completes,    any  thread  can  read  values    wriVen  to  the  final  field    -­‐  and  the  whole  object  tree    

             starCng  from  the  field  

freeze  

Special  semanCcs  of  final  fields    

class  A  {      final  B  ref;      public  A  (…)  {            this.ref  =  …  ;      }  }  

This  should  not  escape  the  constructor:      e.g.  new  Listener(this)  

freeze  

One  more  Cme!  

Java  Memory  Model  

•  Variables:  fields    

•  OperaCons:  – R/W  of  instance  fields  (read/write)  – R/W  of  volaCle  fields  (volaCle  read/write)  – SynchronizaCon  (lock/unlock)  

Java  Memory  Model    

Atomicity    

Visibility    

Reordering  

Atomicity  

•  Read/write  operaCons  are  atomic    •  No  out  of  thin-­‐air  values:  – Any  variable  read  operaCon  should  return  either  a  default  value,  or  the  value  that  was  assigned  to  this  variable  (somewhere  else)  

Atomicity  

•  ExcepCon:  – It  is  allowed  that  reads/writes  of  long/double  type  is  not  atomic,  but..  

– …  read/write  of  vola9le  long/double  must  be  atomic  

Atomicity  

•  A  common  mistake:  – For  volaCle  long/double  only  the  reads  and  writes  are  atomic  

–  foo++,  foo-­‐-­‐  are  not  atomic!  

•  SoluCon:  – synchronized  –  java.u5l.concurrent.atomic  

Visibility  

•  Again,  the  happens-­‐before  relaCon:  –  If  X  happens-­‐before  Y,  then  operaCon  X  is  executed  before  and  Y  will  will  see  the  result  of  X  

Visibility  guarantees  

•  Changes  made  in  one  thread  are  guaranteed  to  be  visible  to  other  threads  under  following  condiCons:  –  Explicit  synchronizaCon  –  Thread  start  and  terminaCon  –  Read/write  of  volaCles  –  First  read  of  finals    

•  Thus,  visibility  is  an  issue  in  case  if  the  access  is  not  synchronized  

Ordering  

•  Within  a  thread  – Program  order,  as-­‐if-­‐sequenCal  execuCon  – Reordering  is  possible  as  long  as  currently  execuCng  thread  cannot  tell  the  difference  (data  dependencies)  

Ordering  Guarantees  

•  Ordering  of  synchronized  blocks  is  preserved  – AcCons  in  one  synchronized  block  happen  before  thread  acquires  the  same  lock  

•  Ordering  of  read/write  of  volaCle  fields  is  preserved  –  Effect  of  last  write  to  volaCle  is  visible  to  all  subsequent  reads  of  the  same  volaCle  

•  Ordering  of  iniCalizaCon/access  of  final  fields  is  preserved  – All  threads  will  see    the  correct    values  of  final  fields  that  where  set  by  the  constructor  

x  =  y  =  0  

r1  =  x  

y  =  1  

r2  =  y  

x  =  r2  

Thread  1   Thread  2  

How  can  the  result  be  r1  ==  r2  ==  1  ?  

start  threads  

The  result  is  possible  if  T1’s  acCons  are  reordered  

x  =  y  =  0  

y  =  1  

r1  =  x  

r2  =  y  

x  =  r2  

Thread  1   Thread  2  start  threads  

y  =  1   r2  =  y   x  =  r2   r1  =  x  

r1  ==  r2  ==  1    

References  /  Reading  •  JLS,  Chapter  17:  

hVp://docs.oracle.com/javase/specs/jls/se7/html/jls-­‐17.html  •  Links:  hVp://www.cs.umd.edu/~pugh/java/memoryModel/  •  JavaZone  video:  hVps://vimeo.com/28763316    

•  Ulrich  Drepper.  What  Every  Programmer  Should  Know  About  Memory  

•  D.  Aspinall,  J.  Sevcik.  Java  Memory  Model  Examples:  Good,  Bad  and  Ugly  

•  J.  Mason,  W.  Pugh,  S.  V.  Adve.  Java  Memory  Model  

top related