<Insert Picture Here>      Java Memory Model




Sergey Kuksenko
Java Platform Performance
Agenda


•   Для чего?       <Insert Picture Here>



•   Из-за чего?
•   Как
•   Примеры
•   Сколько стоит




                                       2
"Requirements for Programming Language Memory Models"
Jeremy Manson and William Pugh

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




                                                        3
Agenda


•   Для чего?       <Insert Picture Here>



•   Из-за чего?
•   Как
•   Примеры
•   Сколько стоит




                                       4
Memory wall
• 1980
  – скорость одной операции CPU ~ скорость одного доступа к памяти
• 2010
  – скорость CPU выросла более чем в 10000 раз
  – скорость памяти выросла в ~10 раз




                                                                     5
The Free Lunch Is Over
• 1980
  – скорость одной операции CPU ~ скорость одного доступа к памяти
• 2010
  – скорость CPU выросла более чем в 10000 раз
  – скорость памяти выросла в ~10 раз


• 2005 “The Free Lunch Is Over”
              http://www.gotw.ca/publications/concurrency-ddj.htm
  – увеличиваем количество CPU



                                                                     6
в итоге

• Сложная архитектура современных CPU
  – многоядерность
  – OoO (Out of Order execution)
  – Store buffers (+ store forwarding)
  – Сложная иерархия кешей
  – Протоколы когерентности кешей (MESI, MOESI, MESIF, …)
  – NUMA, ccNUMA
• “Умные” компиляторы



                                                            7
Пример 1
 Начальные значения: A == B == 0

  Thread 1    Thread 2

   r1 = B;     r2 = A;
   A = 1;      B = 1;




                                   8
Пример 1
 Начальные значения: A == B == 0

  Thread 1    Thread 2             Какие значения могут быть
                                           для r1 и r2?
   r1 = B;     r2 = A;
   A = 1;      B = 1;




                                                               9
Пример 1
 Начальные значения: A == B == 0

  Thread 1    Thread 2             Какие значения могут быть
                                           для r1 и r2?
   r1 = B;     r2 = A;
   A = 1;      B = 1;
                                               <r1, r2>
                                          1)   < 0, 0 >   ?
                                          2)   < 0, 1 >   ?
                                          3)   < 1, 0 >   ?
                                          4)   < 1, 1 >   ?



                                                               10
Пример 1
 Начальные значения: A == B == 0

  Thread 1    Thread 2             Какие значения могут быть
                                           для r1 и r2?
   r1 = B;     r2 = A;
   A = 1;      B = 1;
                                               <r1, r2>
                                          1)   < 0, 0 >   +
                                          2)   < 0, 1 >   +
                                          3)   < 1, 0 >   +
                 Reordering               4)   < 1, 1 >   +



                                                               11
Пример 2
 Начальные значения: A == B == 0

  Thread 1       Thread 2           Thread 3

   A = 1;      while( A != 1 ) ;   while( B != 1 ) ;
               B = 1;              r1 = A;




                                                       12
Пример 2
 Начальные значения: A == B == 0

  Thread 1       Thread 2           Thread 3
                                                       Результат:
   A = 1;      while( A != 1 ) ;   while( B != 1 ) ;
                                                         r1 == 1
               B = 1;              r1 = A;
                                                        или (xor) ?
                                                         r1 == 0




                                                                      13
Пример 2
    Начальные значения: A == B == 0

     Thread 1       Thread 2           Thread 3
                                                          Результат:
      A = 1;      while( A != 1 ) ;   while( B != 1 ) ;
                                                            r1 == 1
                  B = 1;              r1 = A;
                                                           или (or) !
                                                            r1 == 0
                               Visibility
Возможно:
   Thread 2 видит write A первым потоком
   Thread 3 видит write B вторым потоком ПЕРЕД тем как увидит write A


                                                                        14
Кто виноват?




 program       execution   visibility
   order         order       order




                                        15
Кто виноват?
               Компилятор




 program         execution   visibility
   order           order       order




                                          16
Кто виноват?
                     Компилятор




 program                execution              visibility
   order                  order                  order




               OoO                     HW
           (Out of Order)           memory model


                                                            17
Def: “операция завершилась”


 A=1;                 Как определить,
               что “операция завершилась”?
 ...




                                             18
Def: “операция завершилась”


 A=1;                   Как определить,
                 что “операция завершилась”?
 ...


      А) Началось исполнение следующей операции.
      Б) Значение оказалось в основной памяти.
      Ц) Результат записи виден в точке использования.




                                                         19
Def: “операция завершилась”


 A=1;                   Как определить,
                 что “операция завершилась”?
 ...


      А) Началось исполнение следующей операции.
      Б) Значение оказалось в основной памяти.
      Ц) Результат записи виден в точке использования.




                                                         20
Атомарность

• Atomicity
                                Нарушения атомарности:
int A = 0xABCDFFFF;
                      – Целевая платформа не содержит операции
                       32битной записи (e.g. только 16 бит) => раздельная
                       запись старшей и младшей частей.

                      – x86: адрес A не выровнен относительно размера.




                                                                         21
Основные свойства модели памяти


• Atomicity (атомарность)

• Visibility (видимость)

• Ordering (порядок)




                                  22
Agenda


•   Для чего?       <Insert Picture Here>



•   Из-за чего?
•   Как!
•   Примеры
•   Сколько стоит




                                      23
Старая JMM


Thread 1     thread            thread   Thread 2
              local             local
             memory            memory
   ...;                                    ...;
   ...;                                    ...;




                       Main
                      Memory




                                                   24
Старая JMM


Thread 1     thread            thread   Thread 2
              local             local
             memory            memory
   ...;                                    ...;
   ...;                                    ...;




                       Main
                      Memory




                                                   25
JMM


• Переменные:
  – static field, instance field, array element
• Операции:
  – чтение/запись обычных переменных (read/write)
  – чтение/запись volatile переменных (volatile read/write)
  – синхронизация (lock/unlock)




                                                              26
volatile arrays?


• volatile A[] array;
• volatile – не транзитивно:
  – ...=array;         - volatile read
  – array=...;         - volatile write
  – array[i]=...;      - обычный write
• А если очень нужно?
  – java.util.concurrent.atomic
    (AtomicIntegerArray, AtomicLongArray, AtomicReferenceArray)



                                                                  27
Атомарность


• Операции чтения/записи являются атомарными.

• No out of thin-air values:
  – Всякое чтение переменной возвратит либо значение по
    умолчанию либо значение записанное (где-либо) в эту
    переменную.




                                                          28
Атомарность


• Исключение:
  – Допускается неатомарное чтение/запись для типов
    long/double.

  – Чтение/запись volatile long/double обязано быть
    атомарным.




                                                      29
Атомарность


• Часто встречаемая ошибка:
  – Для volatile long/double только операции чтения/записи
    являются атомарными!
  – v++, v-- – неатомарные операции!


• Что делать?
  – synchronized
  – java.util.concurrent.atomic



                                                             30
Visibility


• Отношение happens-before:

  – Если X happens-before Y, то X выполнится раньше и Y
    будет видеть результат X.




                                                          31
Visibility (happens-before в пределах потока)


• В пределах одного потока:

  – Все операции имеют отношение happens-before в
    соответствии с program order
   (как написано в тексте программы)




                                                    32
Visibility (happens-before)


• happens-before транзитивно:

  – Если X happens-before Y и Y happens-before Z,
    то X happens-before Z.




                                                    33
Visibility (happens-before между потоками)
Thread 1
                                         Thread 2

               ...
                                   ...
                                                    На одном
           unlock(M1)                               и том же
                                lock(M1)            мониторе!
               ...
                                   ...




                                                                34
Visibility (happens-before между потоками)
Thread 1
                                        Thread 2
                                                   V - volatile
              ...
                                  ...
                                                    На одной
           write(V)                                  и той же
                                read(V)            переменной!
              ...
                                  ...




                                                                  35
Visibility (happens-before между потоками)


• thread.start() → первое действие в потоке
• Последнее действие в потоке → join(), isAlive()
• Запись default value в любую переменную → первое
  действие в потоке




                                                     36
Reordering

• Допустимые перестановки внутри одного треда:
  – Обычные read/write с точностью до зависимости по
    данным.


• Volatile read/write и lock/unlock не могут
  переупорядочиваться.




                                                       37
Reordering

             read/write
                          Roach motel

               lock


             read/write


              unlock


             read/write


                                        38
Reordering


      read/write       read/write




     volatile write   volatile read



      read/write       read/write




                                      39
Пример 3
 Начальные значения:
 int A = 0;
 boolean ready = false;                Что будет напечатано?
   Thread 1    Thread 2
                                        - ничего
A = 41;       while(!ready);            - 0
A = 42;       System.out.println(A);    - 41
ready = true;
                                        - 42
A = 43;
                                        - 43




                                                               40
Пример 3
 Начальные значения:
 int A = 0;
 boolean ready = false;                Что будет напечатано?
   Thread 1    Thread 2
                                        - ничего   +
A = 41;       while(!ready);            - 0        +
A = 42;       System.out.println(A);    - 41       +
ready = true;
                                        - 42       +
A = 43;
                                        - 43       +




                                                               41
Пример 4
 Начальные значения:
 int A = 0;
 volatile boolean ready = false;       Что будет напечатано?
   Thread 1    Thread 2
                                        - ничего
A = 41;       while(!ready);            - 0
A = 42;       System.out.println(A);    - 41
ready = true;
                                        - 42
A = 43;
                                        - 43




                                                               42
Пример 4
 Начальные значения:
 int A = 0;
 volatile boolean ready = false;       Что будет напечатано?
   Thread 1    Thread 2
                                        - ничего
A = 41;       while(!ready);            - 0
A = 42;       System.out.println(A);    - 41
ready = true;
                                        - 42     +
A = 43;
                                        - 43     +




                                                               43
Специальная семантика final полей


 class A {               • После завершения конструктора
    final B ref;           любой тред видит значения
    public A(...){         записаные в final поле
      this.ref=...;        – а также все дерево объектов начиная
    }                        с этого поля (dereference-chain).
    …
 }           fre
                   ez
                     e



                                                                   44
Специальная семантика final полей


 class A {               • Требуется - this не должен убегать
    final B ref;           (escape) из конструктора.
    public A(...){         – e.g. регистрация listener в его-же
      this.ref=...;          конструкторе.
    }                    • Модификации в final dereference-chain
    …                      выполненные после завершения
 }           fre           конструктора подчиняются обычным
                   ez      правилам видимости.
                     e



                                                                   45
Agenda


•   Для чего?       <Insert Picture Here>



•   Из-за чего?
•   Как
•   Примеры
•   Сколько стоит




                                      46
Double-checked locking
class Foo {
    private Helper helper = null;
    public Helper getHelper() {
          if (helper == null)
              synchronized(this) {
                  if (helper == null)
                      helper = new Helper();
              }
          return helper;
    }
    ...
}

                                               47
Double-checked locking
class Foo {
    private volatile Helper helper = null;
    public Helper getHelper() {
          if (helper == null)
              synchronized(this) {
                  if (helper == null)
                      helper = new Helper();
              }
          return helper;
    }
    ...
}

                                               48
Double-checked locking (is it correct?)
class Foo {
    private static volatile List<A> list = null;
    public static List<A> getList() {
        if (list == null)
              synchronized(Foo.class) {
                  if (list == null)
                       list = new ArrayList<A>();
                       list.add(...); list.add(...);
                  }
              }
        return list;
    }
}
                                                       49
Yet another fail

class Foo {
    private A something;
    public synchronized void setSomething(B b) {
        A a = evaluate_A_from_B();
        this.something = a;
    }
    public A getSomething() {
        return this.something;
    }
}


                                                   50
Yet another fail (fix 1)

class Foo {
    private A something;
    public synchronized void setSomething(B b) {
        A a = evaluate_A_from_B();
        this.something = a;
    }
    public synchronized A getSomething() {
        return this.something;
    }
}


                                                   51
Yet another fail (fix 2)

class Foo {
    private volatile A something;
    public synchronized void setSomething(B b) {
        A a = evaluate_A_from_B();
        this.something = a;
    }
    public A getSomething() {
        return this.something;
    }
}


                                                   52
Agenda


•   Для чего?       <Insert Picture Here>



•   Из-за чего?
•   Как
•   Примеры
•   Сколько стоит




                                      53
Производительность


• Как измерить скорость volatile read/write?
  – Влияние HW memory model
  – Влияние на оптимизации компилятора


• x86:
  – volatile read == обычный read
  – volatile write?




                                               54
Тест 1
Тест не измеряет ничего реального
   1 operation :
for(...) { //128 times
   v = arr[i]++;
}
                 – 129 операций чтения (всегда non-shared, thread local)
                 – 128 операций записи (всегда non-shared, thread local)
                 – немного арифметики
                 – 128 oпераций записи (4 варианта теста):
                     – shared / non shared
                     – volatile / non volatile




                                                                           55
i5 (2 core, +HT) = 4 HW threads




                                  56
Intel Westmere-EX (E7-4860) 2.27Ghz, 4x10x2 = 80 HW threads, RHEL 5.5




                                                                        57
Intel Westmere-EX (E7-4860) 2.27Ghz, 4x10x2 = 80 HW threads, RHEL 5.5




                                                                        58
Intel Westmere-EX (E7-4860) 2.27Ghz, 4x10x2 = 80 HW threads, RHEL 5.5




                                                                        59
Тест 2

private int[] array = new int[10000];
...
public void test(){
    int s = 0;
    for(int i=0; i<array.length; i++) {
       s+=array[i];
    }
    sum = s;
}




                                          60
Тест 2 (rev. 1)
                                          i5 (2 core, +HT) = 4 HW threads
private int[] array = new int[10000];
...
public void test(){
    int s = 0;                            Throughput = 495 ops/msec
    for(int i=0; i<array.length; i++) {
       s+=array[i];
    }
    sum = s;
}




                                                                            61
Тест 2 (rev. 2)
                                                 i5 (2 core, +HT) = 4 HW threads
private volatile int[] array = new int[10000];
...
public void test(){
    int s = 0;                                   Throughput = 62 ops/msec
    for(int i=0; i<array.length; i++) {
       s+=array[i];
    }
    sum = s;
}




                                                                                   62
Тест 2 (rev. 3)
                                                 i5 (2 core, +HT) = 4 HW threads
private volatile int[] array = new int[10000];
...
public void test(){
    int s = 0;                                   Throughput = 495 ops/msec
    int[] a = array;
    for(int i=0; i<a.length; i++) {
       s+=a[i];
    }
    sum = s;
}




                                                                                   63
Читаем

• "Java Concurrency in Practice", Brian Goetz, Tim Peierls, Joshua Bloch,
  Joseph Bowbeer, David Holmes, Doug Lea
• "The Art of Multiprocessor Programming", Maurice Herlihy, Nir Shavit
• “A Little Book of Semaphores”, Allen B. Downey
  – http://greenteapress.com/semaphores/
• “JSR 133 Cookbook”
  – http://g.oswego.edu/dl/jmm/cookbook.html
• "What Every Programmer Should Know About Memory", Ulrich Drepper
   – http://www.akkadia.org/drepper/cpumemory.pdf



                                                                            64
Q&A ?


        65

Java Memory Model

  • 1.
    <Insert Picture Here> Java Memory Model Sergey Kuksenko Java Platform Performance
  • 2.
    Agenda • Для чего? <Insert Picture Here> • Из-за чего? • Как • Примеры • Сколько стоит 2
  • 3.
    "Requirements for ProgrammingLanguage Memory Models" Jeremy Manson and William Pugh “If programmers don’t know what their code is doing, programmers won’t be able to know what their code is doing wrong.” 3
  • 4.
    Agenda • Для чего? <Insert Picture Here> • Из-за чего? • Как • Примеры • Сколько стоит 4
  • 5.
    Memory wall • 1980 – скорость одной операции CPU ~ скорость одного доступа к памяти • 2010 – скорость CPU выросла более чем в 10000 раз – скорость памяти выросла в ~10 раз 5
  • 6.
    The Free LunchIs Over • 1980 – скорость одной операции CPU ~ скорость одного доступа к памяти • 2010 – скорость CPU выросла более чем в 10000 раз – скорость памяти выросла в ~10 раз • 2005 “The Free Lunch Is Over” http://www.gotw.ca/publications/concurrency-ddj.htm – увеличиваем количество CPU 6
  • 7.
    в итоге • Сложнаяархитектура современных CPU – многоядерность – OoO (Out of Order execution) – Store buffers (+ store forwarding) – Сложная иерархия кешей – Протоколы когерентности кешей (MESI, MOESI, MESIF, …) – NUMA, ccNUMA • “Умные” компиляторы 7
  • 8.
    Пример 1 Начальныезначения: A == B == 0 Thread 1 Thread 2 r1 = B; r2 = A; A = 1; B = 1; 8
  • 9.
    Пример 1 Начальныезначения: A == B == 0 Thread 1 Thread 2 Какие значения могут быть для r1 и r2? r1 = B; r2 = A; A = 1; B = 1; 9
  • 10.
    Пример 1 Начальныезначения: A == B == 0 Thread 1 Thread 2 Какие значения могут быть для r1 и r2? r1 = B; r2 = A; A = 1; B = 1; <r1, r2> 1) < 0, 0 > ? 2) < 0, 1 > ? 3) < 1, 0 > ? 4) < 1, 1 > ? 10
  • 11.
    Пример 1 Начальныезначения: A == B == 0 Thread 1 Thread 2 Какие значения могут быть для r1 и r2? r1 = B; r2 = A; A = 1; B = 1; <r1, r2> 1) < 0, 0 > + 2) < 0, 1 > + 3) < 1, 0 > + Reordering 4) < 1, 1 > + 11
  • 12.
    Пример 2 Начальныезначения: A == B == 0 Thread 1 Thread 2 Thread 3 A = 1; while( A != 1 ) ; while( B != 1 ) ; B = 1; r1 = A; 12
  • 13.
    Пример 2 Начальныезначения: A == B == 0 Thread 1 Thread 2 Thread 3 Результат: A = 1; while( A != 1 ) ; while( B != 1 ) ; r1 == 1 B = 1; r1 = A; или (xor) ? r1 == 0 13
  • 14.
    Пример 2 Начальные значения: A == B == 0 Thread 1 Thread 2 Thread 3 Результат: A = 1; while( A != 1 ) ; while( B != 1 ) ; r1 == 1 B = 1; r1 = A; или (or) ! r1 == 0 Visibility Возможно: Thread 2 видит write A первым потоком Thread 3 видит write B вторым потоком ПЕРЕД тем как увидит write A 14
  • 15.
    Кто виноват? program execution visibility order order order 15
  • 16.
    Кто виноват? Компилятор program execution visibility order order order 16
  • 17.
    Кто виноват? Компилятор program execution visibility order order order OoO HW (Out of Order) memory model 17
  • 18.
    Def: “операция завершилась” A=1; Как определить, что “операция завершилась”? ... 18
  • 19.
    Def: “операция завершилась” A=1; Как определить, что “операция завершилась”? ... А) Началось исполнение следующей операции. Б) Значение оказалось в основной памяти. Ц) Результат записи виден в точке использования. 19
  • 20.
    Def: “операция завершилась” A=1; Как определить, что “операция завершилась”? ... А) Началось исполнение следующей операции. Б) Значение оказалось в основной памяти. Ц) Результат записи виден в точке использования. 20
  • 21.
    Атомарность • Atomicity Нарушения атомарности: int A = 0xABCDFFFF; – Целевая платформа не содержит операции 32битной записи (e.g. только 16 бит) => раздельная запись старшей и младшей частей. – x86: адрес A не выровнен относительно размера. 21
  • 22.
    Основные свойства моделипамяти • Atomicity (атомарность) • Visibility (видимость) • Ordering (порядок) 22
  • 23.
    Agenda • Для чего? <Insert Picture Here> • Из-за чего? • Как! • Примеры • Сколько стоит 23
  • 24.
    Старая JMM Thread 1 thread thread Thread 2 local local memory memory ...; ...; ...; ...; Main Memory 24
  • 25.
    Старая JMM Thread 1 thread thread Thread 2 local local memory memory ...; ...; ...; ...; Main Memory 25
  • 26.
    JMM • Переменные: – static field, instance field, array element • Операции: – чтение/запись обычных переменных (read/write) – чтение/запись volatile переменных (volatile read/write) – синхронизация (lock/unlock) 26
  • 27.
    volatile arrays? • volatileA[] array; • volatile – не транзитивно: – ...=array; - volatile read – array=...; - volatile write – array[i]=...; - обычный write • А если очень нужно? – java.util.concurrent.atomic (AtomicIntegerArray, AtomicLongArray, AtomicReferenceArray) 27
  • 28.
    Атомарность • Операции чтения/записиявляются атомарными. • No out of thin-air values: – Всякое чтение переменной возвратит либо значение по умолчанию либо значение записанное (где-либо) в эту переменную. 28
  • 29.
    Атомарность • Исключение: – Допускается неатомарное чтение/запись для типов long/double. – Чтение/запись volatile long/double обязано быть атомарным. 29
  • 30.
    Атомарность • Часто встречаемаяошибка: – Для volatile long/double только операции чтения/записи являются атомарными! – v++, v-- – неатомарные операции! • Что делать? – synchronized – java.util.concurrent.atomic 30
  • 31.
    Visibility • Отношение happens-before: – Если X happens-before Y, то X выполнится раньше и Y будет видеть результат X. 31
  • 32.
    Visibility (happens-before впределах потока) • В пределах одного потока: – Все операции имеют отношение happens-before в соответствии с program order (как написано в тексте программы) 32
  • 33.
    Visibility (happens-before) • happens-beforeтранзитивно: – Если X happens-before Y и Y happens-before Z, то X happens-before Z. 33
  • 34.
    Visibility (happens-before междупотоками) Thread 1 Thread 2 ... ... На одном unlock(M1) и том же lock(M1) мониторе! ... ... 34
  • 35.
    Visibility (happens-before междупотоками) Thread 1 Thread 2 V - volatile ... ... На одной write(V) и той же read(V) переменной! ... ... 35
  • 36.
    Visibility (happens-before междупотоками) • thread.start() → первое действие в потоке • Последнее действие в потоке → join(), isAlive() • Запись default value в любую переменную → первое действие в потоке 36
  • 37.
    Reordering • Допустимые перестановкивнутри одного треда: – Обычные read/write с точностью до зависимости по данным. • Volatile read/write и lock/unlock не могут переупорядочиваться. 37
  • 38.
    Reordering read/write Roach motel lock read/write unlock read/write 38
  • 39.
    Reordering read/write read/write volatile write volatile read read/write read/write 39
  • 40.
    Пример 3 Начальныезначения: int A = 0; boolean ready = false; Что будет напечатано? Thread 1 Thread 2 - ничего A = 41; while(!ready); - 0 A = 42; System.out.println(A); - 41 ready = true; - 42 A = 43; - 43 40
  • 41.
    Пример 3 Начальныезначения: int A = 0; boolean ready = false; Что будет напечатано? Thread 1 Thread 2 - ничего + A = 41; while(!ready); - 0 + A = 42; System.out.println(A); - 41 + ready = true; - 42 + A = 43; - 43 + 41
  • 42.
    Пример 4 Начальныезначения: int A = 0; volatile boolean ready = false; Что будет напечатано? Thread 1 Thread 2 - ничего A = 41; while(!ready); - 0 A = 42; System.out.println(A); - 41 ready = true; - 42 A = 43; - 43 42
  • 43.
    Пример 4 Начальныезначения: int A = 0; volatile boolean ready = false; Что будет напечатано? Thread 1 Thread 2 - ничего A = 41; while(!ready); - 0 A = 42; System.out.println(A); - 41 ready = true; - 42 + A = 43; - 43 + 43
  • 44.
    Специальная семантика finalполей class A { • После завершения конструктора final B ref; любой тред видит значения public A(...){ записаные в final поле this.ref=...; – а также все дерево объектов начиная } с этого поля (dereference-chain). … } fre ez e 44
  • 45.
    Специальная семантика finalполей class A { • Требуется - this не должен убегать final B ref; (escape) из конструктора. public A(...){ – e.g. регистрация listener в его-же this.ref=...; конструкторе. } • Модификации в final dereference-chain … выполненные после завершения } fre конструктора подчиняются обычным ez правилам видимости. e 45
  • 46.
    Agenda • Для чего? <Insert Picture Here> • Из-за чего? • Как • Примеры • Сколько стоит 46
  • 47.
    Double-checked locking class Foo{ private Helper helper = null; public Helper getHelper() { if (helper == null) synchronized(this) { if (helper == null) helper = new Helper(); } return helper; } ... } 47
  • 48.
    Double-checked locking class Foo{ private volatile Helper helper = null; public Helper getHelper() { if (helper == null) synchronized(this) { if (helper == null) helper = new Helper(); } return helper; } ... } 48
  • 49.
    Double-checked locking (isit correct?) class Foo { private static volatile List<A> list = null; public static List<A> getList() { if (list == null) synchronized(Foo.class) { if (list == null) list = new ArrayList<A>(); list.add(...); list.add(...); } } return list; } } 49
  • 50.
    Yet another fail classFoo { private A something; public synchronized void setSomething(B b) { A a = evaluate_A_from_B(); this.something = a; } public A getSomething() { return this.something; } } 50
  • 51.
    Yet another fail(fix 1) class Foo { private A something; public synchronized void setSomething(B b) { A a = evaluate_A_from_B(); this.something = a; } public synchronized A getSomething() { return this.something; } } 51
  • 52.
    Yet another fail(fix 2) class Foo { private volatile A something; public synchronized void setSomething(B b) { A a = evaluate_A_from_B(); this.something = a; } public A getSomething() { return this.something; } } 52
  • 53.
    Agenda • Для чего? <Insert Picture Here> • Из-за чего? • Как • Примеры • Сколько стоит 53
  • 54.
    Производительность • Как измеритьскорость volatile read/write? – Влияние HW memory model – Влияние на оптимизации компилятора • x86: – volatile read == обычный read – volatile write? 54
  • 55.
    Тест 1 Тест неизмеряет ничего реального 1 operation : for(...) { //128 times v = arr[i]++; } – 129 операций чтения (всегда non-shared, thread local) – 128 операций записи (всегда non-shared, thread local) – немного арифметики – 128 oпераций записи (4 варианта теста): – shared / non shared – volatile / non volatile 55
  • 56.
    i5 (2 core,+HT) = 4 HW threads 56
  • 57.
    Intel Westmere-EX (E7-4860)2.27Ghz, 4x10x2 = 80 HW threads, RHEL 5.5 57
  • 58.
    Intel Westmere-EX (E7-4860)2.27Ghz, 4x10x2 = 80 HW threads, RHEL 5.5 58
  • 59.
    Intel Westmere-EX (E7-4860)2.27Ghz, 4x10x2 = 80 HW threads, RHEL 5.5 59
  • 60.
    Тест 2 private int[]array = new int[10000]; ... public void test(){ int s = 0; for(int i=0; i<array.length; i++) { s+=array[i]; } sum = s; } 60
  • 61.
    Тест 2 (rev.1) i5 (2 core, +HT) = 4 HW threads private int[] array = new int[10000]; ... public void test(){ int s = 0; Throughput = 495 ops/msec for(int i=0; i<array.length; i++) { s+=array[i]; } sum = s; } 61
  • 62.
    Тест 2 (rev.2) i5 (2 core, +HT) = 4 HW threads private volatile int[] array = new int[10000]; ... public void test(){ int s = 0; Throughput = 62 ops/msec for(int i=0; i<array.length; i++) { s+=array[i]; } sum = s; } 62
  • 63.
    Тест 2 (rev.3) i5 (2 core, +HT) = 4 HW threads private volatile int[] array = new int[10000]; ... public void test(){ int s = 0; Throughput = 495 ops/msec int[] a = array; for(int i=0; i<a.length; i++) { s+=a[i]; } sum = s; } 63
  • 64.
    Читаем • "Java Concurrencyin Practice", Brian Goetz, Tim Peierls, Joshua Bloch, Joseph Bowbeer, David Holmes, Doug Lea • "The Art of Multiprocessor Programming", Maurice Herlihy, Nir Shavit • “A Little Book of Semaphores”, Allen B. Downey – http://greenteapress.com/semaphores/ • “JSR 133 Cookbook” – http://g.oswego.edu/dl/jmm/cookbook.html • "What Every Programmer Should Know About Memory", Ulrich Drepper – http://www.akkadia.org/drepper/cpumemory.pdf 64
  • 65.