Java Memory Model

2,261 views

Published on

0 Comments
2 Likes
Statistics
Notes
  • Be the first to comment

No Downloads
Views
Total views
2,261
On SlideShare
0
From Embeds
0
Number of Embeds
3
Actions
Shares
0
Downloads
42
Comments
0
Likes
2
Embeds 0
No embeds

No notes for slide

Java Memory Model

  1. 1. <Insert Picture Here> Java Memory ModelSergey KuksenkoJava Platform Performance
  2. 2. Agenda• Для чего? <Insert Picture Here>• Из-за чего?• Как• Примеры• Сколько стоит 2
  3. 3. "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
  4. 4. Agenda• Для чего? <Insert Picture Here>• Из-за чего?• Как• Примеры• Сколько стоит 4
  5. 5. Memory wall• 1980 – скорость одной операции CPU ~ скорость одного доступа к памяти• 2010 – скорость CPU выросла более чем в 10000 раз – скорость памяти выросла в ~10 раз 5
  6. 6. 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
  7. 7. в итоге• Сложная архитектура современных CPU – многоядерность – OoO (Out of Order execution) – Store buffers (+ store forwarding) – Сложная иерархия кешей – Протоколы когерентности кешей (MESI, MOESI, MESIF, …) – NUMA, ccNUMA• “Умные” компиляторы 7
  8. 8. Пример 1 Начальные значения: A == B == 0 Thread 1 Thread 2 r1 = B; r2 = A; A = 1; B = 1; 8
  9. 9. Пример 1 Начальные значения: A == B == 0 Thread 1 Thread 2 Какие значения могут быть для r1 и r2? r1 = B; r2 = A; A = 1; B = 1; 9
  10. 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. 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. 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. 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. 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. 15. Кто виноват? program execution visibility order order order 15
  16. 16. Кто виноват? Компилятор program execution visibility order order order 16
  17. 17. Кто виноват? Компилятор program execution visibility order order order OoO HW (Out of Order) memory model 17
  18. 18. Def: “операция завершилась” A=1; Как определить, что “операция завершилась”? ... 18
  19. 19. Def: “операция завершилась” A=1; Как определить, что “операция завершилась”? ... А) Началось исполнение следующей операции. Б) Значение оказалось в основной памяти. Ц) Результат записи виден в точке использования. 19
  20. 20. Def: “операция завершилась” A=1; Как определить, что “операция завершилась”? ... А) Началось исполнение следующей операции. Б) Значение оказалось в основной памяти. Ц) Результат записи виден в точке использования. 20
  21. 21. Атомарность• Atomicity Нарушения атомарности:int A = 0xABCDFFFF; – Целевая платформа не содержит операции 32битной записи (e.g. только 16 бит) => раздельная запись старшей и младшей частей. – x86: адрес A не выровнен относительно размера. 21
  22. 22. Основные свойства модели памяти• Atomicity (атомарность)• Visibility (видимость)• Ordering (порядок) 22
  23. 23. Agenda• Для чего? <Insert Picture Here>• Из-за чего?• Как!• Примеры• Сколько стоит 23
  24. 24. Старая JMMThread 1 thread thread Thread 2 local local memory memory ...; ...; ...; ...; Main Memory 24
  25. 25. Старая JMMThread 1 thread thread Thread 2 local local memory memory ...; ...; ...; ...; Main Memory 25
  26. 26. JMM• Переменные: – static field, instance field, array element• Операции: – чтение/запись обычных переменных (read/write) – чтение/запись volatile переменных (volatile read/write) – синхронизация (lock/unlock) 26
  27. 27. volatile arrays?• volatile A[] array;• volatile – не транзитивно: – ...=array; - volatile read – array=...; - volatile write – array[i]=...; - обычный write• А если очень нужно? – java.util.concurrent.atomic (AtomicIntegerArray, AtomicLongArray, AtomicReferenceArray) 27
  28. 28. Атомарность• Операции чтения/записи являются атомарными.• No out of thin-air values: – Всякое чтение переменной возвратит либо значение по умолчанию либо значение записанное (где-либо) в эту переменную. 28
  29. 29. Атомарность• Исключение: – Допускается неатомарное чтение/запись для типов long/double. – Чтение/запись volatile long/double обязано быть атомарным. 29
  30. 30. Атомарность• Часто встречаемая ошибка: – Для volatile long/double только операции чтения/записи являются атомарными! – v++, v-- – неатомарные операции!• Что делать? – synchronized – java.util.concurrent.atomic 30
  31. 31. Visibility• Отношение happens-before: – Если X happens-before Y, то X выполнится раньше и Y будет видеть результат X. 31
  32. 32. Visibility (happens-before в пределах потока)• В пределах одного потока: – Все операции имеют отношение happens-before в соответствии с program order (как написано в тексте программы) 32
  33. 33. Visibility (happens-before)• happens-before транзитивно: – Если X happens-before Y и Y happens-before Z, то X happens-before Z. 33
  34. 34. Visibility (happens-before между потоками)Thread 1 Thread 2 ... ... На одном unlock(M1) и том же lock(M1) мониторе! ... ... 34
  35. 35. Visibility (happens-before между потоками)Thread 1 Thread 2 V - volatile ... ... На одной write(V) и той же read(V) переменной! ... ... 35
  36. 36. Visibility (happens-before между потоками)• thread.start() → первое действие в потоке• Последнее действие в потоке → join(), isAlive()• Запись default value в любую переменную → первое действие в потоке 36
  37. 37. Reordering• Допустимые перестановки внутри одного треда: – Обычные read/write с точностью до зависимости по данным.• Volatile read/write и lock/unlock не могут переупорядочиваться. 37
  38. 38. Reordering read/write Roach motel lock read/write unlock read/write 38
  39. 39. Reordering read/write read/write volatile write volatile read read/write read/write 39
  40. 40. Пример 3 Начальные значения: int A = 0; boolean ready = false; Что будет напечатано? Thread 1 Thread 2 - ничегоA = 41; while(!ready); - 0A = 42; System.out.println(A); - 41ready = true; - 42A = 43; - 43 40
  41. 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. 42. Пример 4 Начальные значения: int A = 0; volatile boolean ready = false; Что будет напечатано? Thread 1 Thread 2 - ничегоA = 41; while(!ready); - 0A = 42; System.out.println(A); - 41ready = true; - 42A = 43; - 43 42
  43. 43. Пример 4 Начальные значения: int A = 0; volatile boolean ready = false; Что будет напечатано? Thread 1 Thread 2 - ничегоA = 41; while(!ready); - 0A = 42; System.out.println(A); - 41ready = true; - 42 +A = 43; - 43 + 43
  44. 44. Специальная семантика final полей class A { • После завершения конструктора final B ref; любой тред видит значения public A(...){ записаные в final поле this.ref=...; – а также все дерево объектов начиная } с этого поля (dereference-chain). … } fre ez e 44
  45. 45. Специальная семантика final полей class A { • Требуется - this не должен убегать final B ref; (escape) из конструктора. public A(...){ – e.g. регистрация listener в его-же this.ref=...; конструкторе. } • Модификации в final dereference-chain … выполненные после завершения } fre конструктора подчиняются обычным ez правилам видимости. e 45
  46. 46. Agenda• Для чего? <Insert Picture Here>• Из-за чего?• Как• Примеры• Сколько стоит 46
  47. 47. Double-checked lockingclass Foo { private Helper helper = null; public Helper getHelper() { if (helper == null) synchronized(this) { if (helper == null) helper = new Helper(); } return helper; } ...} 47
  48. 48. Double-checked lockingclass Foo { private volatile Helper helper = null; public Helper getHelper() { if (helper == null) synchronized(this) { if (helper == null) helper = new Helper(); } return helper; } ...} 48
  49. 49. 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
  50. 50. Yet another failclass 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
  51. 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. 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. 53. Agenda• Для чего? <Insert Picture Here>• Из-за чего?• Как• Примеры• Сколько стоит 53
  54. 54. Производительность• Как измерить скорость volatile read/write? – Влияние HW memory model – Влияние на оптимизации компилятора• x86: – volatile read == обычный read – volatile write? 54
  55. 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. 56. i5 (2 core, +HT) = 4 HW threads 56
  57. 57. Intel Westmere-EX (E7-4860) 2.27Ghz, 4x10x2 = 80 HW threads, RHEL 5.5 57
  58. 58. Intel Westmere-EX (E7-4860) 2.27Ghz, 4x10x2 = 80 HW threads, RHEL 5.5 58
  59. 59. Intel Westmere-EX (E7-4860) 2.27Ghz, 4x10x2 = 80 HW threads, RHEL 5.5 59
  60. 60. Тест 2private 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. 61. Тест 2 (rev. 1) i5 (2 core, +HT) = 4 HW threadsprivate 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. 62. Тест 2 (rev. 2) i5 (2 core, +HT) = 4 HW threadsprivate 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. 63. Тест 2 (rev. 3) i5 (2 core, +HT) = 4 HW threadsprivate 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. 64. Читаем• "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
  65. 65. Q&A ? 65

×