Similar presentations:
JMM (1)
1. Java Memory Model
2.
УЗНАЕМЧто такое JMM
Reordering
Happens-before relationship
Гарантии volatile
Double-check locking
Singleton pattern и JMM
Safe publication idioms
Immutable и effectively immutable objects
Гарантии final
3.
М О Ж Н О Л И В Ы З В АТ Ь G R E E T ( ) И Н Е У В И Д Е Т Ь “ H E L L O ” ?public class HelloPrinter {
private boolean sayHello = true;
public synchronized void greet() {
if (sayHello) {
System.out.println("hello");
}
sayHello = false;
}
}
4. З АЧ Е М Н У Ж Н А J M M ?
variable = 3;Отвечает на вопрос: ”При каких условиях поток, который прочитал
эту переменную, увидит значение 3?”
5.
З АЧ Е М Н У Ж Н А J M M ?• Описывает как потоки взаимодействуют через память. Когда
изменения, сделанные одним потоком, будут видны другому
• Описывает корректное поведение программы в многопоточной
среде на различных архитектурах с различными hardware memory
model
• Описывает работу с shared variables
6. Оригинальная Java memory model была разработана в 1995 году.
J MMОригинальная Java memory model была разработана в 1995 году.
Была обновлена через Java Community Process (JSR-133) в 2004г.
Изменения появились в Java 5.0.
Описывается в 17 главе JLS:
http://java.sun.com/docs/books/jls/third_edition/html/memory.html
7. x = y = 0
КАКИЕ ВОЗМОЖНЫ ВАРИАНТЫ ?x=y=0
Thread 1
Thread 2
a = x;
y = 1;
b = y;
x = 1;
a=?b=?
8. x = y = 0
КАКИЕ ВОЗМОЖНЫ ВАРИАНТЫ ?x=y=0
Thread 1
Thread 2
a = x;
y = 1;
b = y;
x = 1;
1.
2.
3.
a = 0; b = 0;
a = 1; b = 0;
a = 0; b = 1;
9. x = y = 0
КАКИЕ ВОЗМОЖНЫ ВАРИАНТЫ ?x=y=0
Thread 1
Thread 2
a = x;
y = 1;
b = y;
x = 1;
1.
2.
3.
4.
a = 0; b = 0;
a = 1; b = 0;
a = 0; b = 1;
a = 1; b = 1; oO ?
10. x = y = 0
В О З М О Ж Е Н Р Е О РД Е Р И Н Гx=y=0
Thread 1
Thread 2
a = x;
y = 1;
b = y;
x = 1;
1.
2.
3.
4.
a = 0; b = 0;
a = 1; b = 0;
a = 0; b = 1;
a = 1; b = 1; oO ?
11. x = y = 0
Р Е О РД Е Р И Н Гx=y=0
Thread 1
Thread 2
y = 1;
a = x;
x = 1;
b = y;
1.
2.
3.
4.
a = 0; b = 0;
a = 1; b = 0;
a = 0; b = 1;
a = 1; b = 1;
12. 1. Компилятор может в качестве оптимизации свободно переупорядочивать определенные инструкции, если это не меняет семантику
ИЗ - З А Ч Е Г О П Р О И С Х О Д И Т R E O R D E R I N G ?1. Компилятор может в качестве оптимизации свободно
переупорядочивать определенные инструкции, если это не
меняет семантику программы.
2. Процессору позволяется исполнять операции не по порядку в
некоторых обстоятельствах.
3. Кэшу, как правило, позволяется выполнять обратную запись
переменных в основную память не в том порядке, в котором они
были записаны программой.
13.
H A P P E N S - B E F O R E R E L AT I O N S H I PJMM оперирует терминами actions (read, write, lock, unlock,…)
JMM гарантирует что поток, выполнивший action B увидит результат
действия A, только если A и В состоят в отношении happens-before. (A
happens-before B)
14. JMM оперирует терминами actions (read, write, lock, unlock,…)
H A P P E N S - B E F O R E Т РА Н З И Т И В Е НJMM оперирует терминами actions (read, write, lock, unlock,…)
JMM гарантирует что поток, выполнивший action B увидит результат
действия A, только если A и В состоят в отношении happens-before. (A
happens-before B)
hb(x, y) и hb(y, z), то hb(x, z)
15.
О Б Я З А Н Л И T 2 У В И Д Е Т Ь И З М Е Н Е Н И Я С Д Е Л А Н Н Ы Е T 1?Thread 1
lock M1
Thread 2
lock M2
x=1
temp = x
unlock M1
unlock M2
y=2
temp2 = y
16.
Н Е К О Т О Р Ы Е HB• Действия в потоке happens-before последующего действия в этом же потоке,
которое идет позже в программном порядке
• Разблокировка монитора happens-before каждой последующей блокировки
того же монитора
• Запись в поле volatile happens-before каждого последующего считывания того
же самого volatile
• Вызов Thread::start() у потока happens-before первого действия в этом потоке
• Завершение потока T1 happens-before момента, когда поток T2 определил, что
T1 завершился, вызвав T1.join() или T1.isAlive() (и получив false)
• Завершение конструктора объекта happens-before запуска финализации для
него
• Еще несколько пунктов …
17.
О Б Я З А Н Л И T 2 У В И Д Е Т Ь И З М Е Н Е Н И Я С Д Е Л А Н Н Ы Е T 1?Thread 1
lock M1
Thread 2
lock M2
x=1
temp = x
unlock M1
unlock M2
y=2
temp2 = y
18.
T 2 Н Е О Б Я З А Н У В И Д Е Т Ь И З М Е Н Е Н И Я С Д Е Л А Н Н Ы Е T1Thread 1
lock M1
Thread 2
lock M2
x=1
temp = x
unlock M1
unlock M2
y=2
temp2 = y
19.
О Б Я З А Н Л И T 2 У В И Д Е Т Ь И З М Е Н Е Н И Я С Д Е Л А Н Н Ы Е T 1?Thread 1
lock M1
Thread 2
lock M1
x=1
temp = x
unlock M1
unlock M1
y=2
temp2 = y
20.
О Б Я З А Н Л И T 2 У В И Д Е Т Ь И З М Е Н Е Н И Я С Д Е Л А Н Н Ы Е T 1?Thread 1
lock M1
Thread 2
lock M1
x=1
temp = x
unlock M1
unlock M1
y=2
temp2 = y
да
21.
О Б Я З А Н Л И T 2 У В И Д Е Т Ь И З М Е Н Е Н И Я С Д Е Л А Н Н Ы Е T 1?Thread 1
lock M1
Thread 2
lock M1
x=1
temp = x
да
unlock M1
unlock M1
y=2
temp2 = y
нет
22.
О Б Я З А Н Л И T 2 У В И Д Е Т Ь И З М Е Н Е Н И Я С Д Е Л А Н Н Ы Е T 1?Thread 1
y=2
Thread 2
lock M1
lock M1
temp = x
x=1
unlock M1
unlock M1
temp2 = y
23.
О Б Я З А Н Л И T 2 У В И Д Е Т Ь И З М Е Н Е Н И Я С Д Е Л А Н Н Ы Е T 1?Thread 1
y=2
Thread 2
lock M1
lock M1
temp = x
да
x=1
unlock M1
unlock M1
temp2 = y
да
24.
О Б Я З А Н Л И T 2 У В И Д Е Т Ь И З М Е Н Е Н И Я С Д Е Л А Н Н Ы Е T 1?Thread 1
x=1
y – volatile переменная
Thread 2
temp = y
y=2
temp2 = x
25.
О Б Я З А Н Л И T 2 У В И Д Е Т Ь И З М Е Н Е Н И Я С Д Е Л А Н Н Ы Е T 1?Thread 1
x=1
y – volatile переменная
Thread 2
temp = y
y=2
temp2 = x
да
26.
О Б Я З А Н Л И T 2 У В И Д Е Т Ь И З М Е Н Е Н И Я С Д Е Л А Н Н Ы Е T 1?Thread 1
x=1
y – volatile переменная
Thread 2
temp = y
да
temp2 = x
да
y=2
27. …. synchronized(this) { ……
SYNCHRONIZED И REORDERING….
synchronized(this) {
……
……
}
….
28.
V O L AT I L E И R E O R D E R I N G……
volatile store
……
29.
V O L AT I L E И R E O R D E R I N G……
volatile read
……
30. ГА РА Н Т И И V O L AT I L E
• Гарантии happens-before• Гарантии с reordering
• Атомарные запись и чтение актуальных значений (даже для
Long и Double на 32x разрядных архитектурах)
31. volatile int x = 0;
+ + X Э Т О 3 О П Е РА Ц И И , А Н Е О Д Н Аvolatile int x = 0;
public void increment() {
++x; //todo не делать так
}
32. boolean keepRunning = true;
БЕСКОНЕЧНЫЙ ЦИКЛboolean keepRunning = true;
public void run() {
while(keepRunning) {
…
}
}
public void setKeepRunning(boolean v){…}
33. Point p = new Point(1, 1);
БЕЗОПАСНАЯ ИНИЦИАЛИЗАЦИЯPoint p = new Point(1, 1);
Thread 1 Thread 2
p = new Point(2, 2);
class Point {
int x,y;
}
a = p.getX();
a=?
34. Point p = new Point(1, 1);
БЕЗОПАСНАЯ ИНИЦИАЛИЗАЦИЯPoint p = new Point(1, 1);
Thread 1 Thread 2
p = new Point(2, 2);
a = p.getX();
1. a = 1;
2. a = 2;
35. Point p = new Point(1, 1);
БЕЗОПАСНАЯ ИНИЦИАЛИЗАЦИЯPoint p = new Point(1, 1);
Thread 1 Thread 2
p = new Point(2, 2);
a = p.getX();
1. a = 1;
2. a = 2;
3. a = 0; oO ??
36.
ССЫЛКА НА ОБЪЕКТ МОЖЕТ ВЕРНУТЬСЯ БЫСТРЕЕЗ А В Е Р Ш Е Н И Я К О Н С Т Р У К Т О РА
Point p = new Point(1, 1);
Thread 1 Thread 2
p = new Point(2, 2);
a = p.getX();
1. a = 1;
2. a = 2;
3. a = 0; oO ??
37. Point p = new Point(1, 1);
Э Т О НЕ ПОМОЖЕТPoint p = new Point(1, 1);
Thread 1 Thread 2
synchronized(this) {
a = p.getX();
p = new Point(2, 2);
}
1. a = 1;
2. a = 2;
3. a = 0; oO ??
38. Point p = new Point(1, 1);
Э Т О Т О ЖЕ НЕ ПОМОЖЕТPoint p = new Point(1, 1);
Thread 1 Thread 2
Point temp = new Point(2, 2);
p = temp;
a = p.getX();
1. a = 1;
2. a = 2;
3. a = 0; oO ??
39. public class HelloPrinter { private boolean sayHello;
THREAD -SAFE ЛИ ДАННЫЙ КОД ?public class HelloPrinter {
private boolean sayHello;
HelloPrinter() {
sayHello = true;
}
Конструктор объекта и его синхронизованные методы
не находятся в отношении happens-before
public synchronized void greet() {
if (sayHello) {
System.out.println("hello");
}
sayHello = false;
}
}
40. public class HelloPrinterFactory { private HelloPrinter instance;
DOUBLE-CHECK LOCKING @NOTTHREADSAFEpublic class HelloPrinterFactory {
private HelloPrinter instance;
public HelloPrinter getPrinter() {
if (instance == null) {
synchronized (this) {
if (instance == null) {
instance = new HelloPrinter();
}
}
}
return instance;
}
}
41. public class HelloPrinterFactory { private HelloPrinter instance;
@NOTTHREADSAFE НЕ ПОМОЖЕТpublic class HelloPrinterFactory {
private HelloPrinter instance;
public HelloPrinter getPrinter() {
if (instance == null) {
synchronized (this) {
if (instance == null) {
HelloPrinter temp = new HelloPrinter();
instance = temp;
}
}
}
return instance;
}
42. Ссылка и состояние объекта должны быть видимы потоку.
S AF E P U B L I C AT I O N I D I O M SСсылка и состояние объекта должны быть видимы потоку.
Инициализация в static инициализаторе
Сохранять ссылку на объект в volatile
Сохранять ссылку в final (this не убегает из конструктора)
Сохранять ссылку в поле, корректно используя синхронизацию
43. public class HelloPrinterFactory { private volatile HelloPrinter instance;
DOUBLE-CHECK LOCKING @THREADSAFEpublic class HelloPrinterFactory {
private volatile HelloPrinter instance;
public HelloPrinter getPrinter() {
if (instance == null) {
synchronized (this) {
if (instance == null) {
instance = new HelloPrinter();
}
}
}
return instance;
}
}
44.
DOUBLE-CHECK LOCKING @THREADSAFEpublic class HelloPrinterFactory {
private HelloPrinter instance; //если все поля объекта final
public HelloPrinter getPrinter() {
HelloPrinter temp = this.instance;
if (temp == null) {
synchronized (this) {
if (this.instance == null) {
this.instance = temp = new HelloPrinter();
}
}
}
return temp;
}
}
45. public class HelloPrinterFactory { private int value; // для 32 битных примитивов (не для double и long)
DOUBLE-CHECK LOCKING @THREADSAFEpublic class HelloPrinterFactory {
private int value; // для 32 битных примитивов (не для double и long)
public int getValue() {
int value = this.value;
if (value == null) {
synchronized (this) {
if (this.value == 0) {
value = this.value = compute();
}
}
}
return value;
}
46. public class HelloPrinterFactory { private static final HelloPrinter instance = new HelloPrinter();
С ТАТ И Ч Е С К А Я И Н И Ц И А Л И З А Ц И Я @ T H R E A D S A F Epublic class HelloPrinterFactory {
private static final HelloPrinter instance = new HelloPrinter();
public HelloPrinter getInstance() {
return instance;
}
}
47. public class HelloPrinterFactory { private static class Holder { private static final HelloPrinter instance = new
ЛУЧШИЙ СПОСОБ ЛЕНИВОЙ ИНИЦИАЛИЗАЦИИ @THREADSAFEpublic class HelloPrinterFactory {
private static class Holder {
private static final HelloPrinter instance = new HelloPrinter();
}
public HelloPrinter getInstance() {
return Holder.instance;
}
}
48. Ни Java Memory Model, ни Java language specification не дают определения immutable.
I M M U TA B L E О Б Ъ Е К Т ЫНи Java Memory Model, ни Java language specification не дают
определения immutable.
49. public final class Person { private final int age; private final String name;
I M M U TA B L E ЛИ О Б Ъ Е К Т Ы Д А Н Н О Г О К Л А С С А ?public final class Person {
private final int age;
private final String name;
public Person(int age, String name) {
this.age = age;
this.name = name;
}
public int getAge() { return age; }
public String getName() { return name;}
}
50. public final class Person { private final int age; private final String name;
I M M U TA B L E ЛИ О Б Ъ Е К Т Ы Д А Н Н О Г О К Л А С С А ?public final class Person {
private final int age;
private final String name;
public Person(int age, String name) {
this.age = age;
this.name = name;
}
}
final поля объекта будут корректно инициализированы до
возвращения ссылки на конструируемый объект и видны всем
потокам.
51. public final class Corporation { private final Set<String> employees= new HashSet<String>();
А Ч Т О Е С Л И П ОЛ Е F I N A L , Н О Е Г О С О С Т О Я Н И Е Н Е F I N A L ?public final class Corporation {
private final Set<String> employees= new HashSet<String>();
public Corporation () {
employees.add(“Alex");
employees.add(“Ben");
}
public boolean isEmployee(String name) {
return employees.contains(name);
}
}
52. public final class Corporation { private final Set<String> employees= new HashSet<String>();
@THREADSAFEpublic final class Corporation {
private final Set<String> employees= new HashSet<String>();
public Corporation () {
employees.add(“Alex");
employees.add(“Ben");
}
}
final гарантирует, что ссылка на объект вернется после
завершения конструктора, так что и тут все ок
53. public final class Person { private int age; private String name;
E F F E C T I V E LY I M M U TA B L Epublic final class Person {
private int age;
private String name;
public Person(int age, String name) {
this.age = age;
this.name = name;
}
public int getAge() { return age; }
public String getName() { return name;}
}
54. Одновременно final volatile - некорректная комбинация модификаторов
F I N A L V O L AT I L EОдновременно final volatile - некорректная комбинация
модификаторов
55.
О Б С УД И Л ИЧто такое JMM
Reordering
Happens-before relationship
Гарантии volatile
Safe publication idioms
Гарантии final
programming