«JMM в Android», Максим Ефимов, Redmadrobot

48
JMM in Android Максим Ефимов Android team leader, Google developer expert 0

Transcript of «JMM в Android», Максим Ефимов, Redmadrobot

JMM in Android

Максим ЕфимовAndroid team leader, Google developer expert

0

О чем будем говорить?

• Зачем понадобилась JMM

• Happens-before

• Causality

• Dalvik MM vs JMM

• Dalvik bytecode vs JVM bytecode

1

Естественный порядок

2

int a, b; void foo() { int l1 = a; int l2 = l1 + 10; int l3 = b; int l4 = l2 % 3; }

3

Reordering

int a, b; void foo() { int l1 = a; int l3 = b; int l2 = l1 + 10; int l4 = l2 % 3; }

int a, b; void foo() { int l1 = a; int l2 = l1 + 10; int l3 = b; int l4 = l2 % 3; }

4

Reordering – ограничения

int a, b; void foo() { int l2 = l1 + 10; int l1 = a; int l3 = b; int l4 = l2 % 3; }

int a, b; void foo() { int l1 = a; int l2 = l1 + 10; int l3 = b; int l4 = l2 % 3; }

Reordering не меняет семантику кода водном потоке

Нотация записи

5

A==B==0

r1=AB=1

r2=BA=1

общее для обоих потоков

происходит в первом потоке происходит во втором потоке

r1=? r2=?

Reordering в многопоточности

6

A==B==0

r1=Ar2=B

B=1 A=1

Ожидаем (r1, r2) (0, 0),(1, 1),(0, 1)

A==B==0

r1=Ar2=B

A=1 B=1

Получаем (r1, r2) (0, 0),(1, 1),(0, 1),

(1, 0)

Семантика нарушается

Нужно больше порядка

7

Action 1.1

Action 1.2

Sync action 1

Sync action 2

Action 2.1

Action 2.2

Action 2.3Action 1.3

Action 1.4 Action 2.4

Поток 1 Поток 2

Порядок

междупотоками

Синхронизация

8

Monitor.Lock()

Action 1.2

Monitor.Unlock()

Monitor.Lock()

Action 2.1

Action 2.2

Action 2.3Action 1.3

Action 1.4 Monitor.Unlock()

Поток 1 Поток 2

Data race

9

• Один поток читает данные • Второй поток пишет данные • Эти два действия не синхронизированы

Итоги & QA - I

10

• Reordering оптимизирует код в одном потоке • Reordering ломает семантику многопоточного кода • Нужен порядок между действиями в разных потоках • Без синхронизации ломается семантика

Вопросы?

Базовые принципы

Java memory model

11

«A memory model describes, given a program and an execution trace of that program, whether the execution

trace is a legal execution of the program.»JSR 133

JMM философия

12

Порядок выполнения может быть любой, кроме запрещенных порядков

Что есть в JMM?

13

• Sequential consistency • Happens before • Causality

finals, word tearing…

Sequential consistency

14

Action 1.1

Action 1.2

Action 2.1

Action 2.2

Action 2.3Action 1.2

Action 1.1

Action 1.2

Action 2.1

Action 2.2

Action 2.3Action 1.2

Вариант №1

Вариант №2

Happens before I

15

Monitor.unlock() Monitor.lock()HB

volatile write volatile readHB

Thread.start() 1st thread actionHB

last thread action Thread.terminate()HB

Thread.interrupt() interrupt detectedHB

default write 1st accessHB

constructor finalizerHB

Happens before II

16

read writeHB

one more write read

HBwrite

HB

read writeМожет видеть

+

=

Happens before III

17

N action in thread N+1 action in threadHB

HB пример

18

Monitor.Lock()

x = 1

Monitor.Unlock() Monitor.Lock()

b = xx = 3

Monitor.Unlock()

Поток 1 Поток 2

HBx = 2

b = ?

a = x a = ?

HB достаточно?

19

A==B==0

r1=A if(r1 != 0) B=1

r2=B if(r2 != 0) A=1

Ожидаем (r1, r2) = ?

HB недостаточно

20

A==B==0

r1=A if(r1 != 0) B=1

r2=B if(r2 != 0) A=1

(r1, r2) = (0, 1)

r1=A B=1 if(r1 == 0) B=0

Causality

21

• Все действия группируются на коммиты • Коммиты выстраиваются в строгий порядок • Действие не может попасть в коммит, если это станет причиной состояния гонки

Causality - пример

22

A==B==0

r1=A B=1

r2=BA=r2

A==B==0B = 1

r2 = B

A = r2

r1 = A

A==B==0

r2 = B

A = r2

r1 = AB = 1

Итоги & QA - II

23

JMM

• Разрешено все, что не запрещено • Happens before • Causality

Вопросы?

JMM for DVM?

24

JMM ≠ DMM

JVM vs DVM

25

Stack Register

Картинки из статьи https://markfaction.wordpress.com/2012/07/15/stack-based-vs-register-based-virtual-machine-architecture-and-the-dalvik-vm/

Memory model @ Dalvik

26

DMM

x86 ARM

Memory barriers

27

• read\read • store\store • read\store • store\read

Гарантия порядка

x86 vs ARM

28

• read\read • store\store • read\store • store\read

• read\read• store\store• read\store • store\read

ARM x86

No barriers I

29

A==B==falseA=truer1=B if(!r1) crit()

B=truer2=A if(!r2) crit()

No barriers II

30

A==B==false

A=truer1=B if(!r1) crit()

B=truer2=A

if(!r2) crit()

r1=B

A=true if(!r1) crit()

x86 vs ARM I

31

A==B==0

A=41B=1

loop_until(B==1)r1=A

x86 vs ARM II

32

A==B==0

B=1

A=41

loop_until(B==1)r1=A

A=41B=1 ARM

ARM address dependency

33

[A+8]==B==0

[A+8]=1 store/store B=16

loop: r0=B if(r0==0) goto loop r1 = 8 r2 = [A + r1]

ARM address dependency

34

[A+8]==B==0

[A+8]=1 store/store B=16

loop: r0=B if(r0==0) goto loop r1 = 8 + r0 r2 = [A + r1]

ARM AD limitation

35

A==B==0A = 1 loop_until(A==1)

B = 16loop: r0=B if(r0==0) goto loop r1 = 8 + r0 r2 = [A + r1]

Итоги & QA - III

36

DVM Memory model

• Есть большая зависимость от платформы • Есть адресная зависимость

Вопросы?

Synchronized example

37

public int fooNoSync(int a) { int b; b = a + 10; return b; }

Bytecode

38

public foo(I)I L0 LINENUMBER 34 L0 ILOAD 1 BIPUSH 10 IADD ISTORE 2 L1 LINENUMBER 35 L1 ILOAD 2 IRETURN L2 LOCALVARIABLE this Lgenerator/android/TestJava; L0 L2 0 LOCALVARIABLE a I L0 L2 1 LOCALVARIABLE b I L1 L2 2 MAXSTACK = 2 MAXLOCALS = 3

.method public foo(I)I .registers 3 .param p1, "a" # I

.prologue .line 27 add-int/lit8 v0, p1, 0xa

.line 29 .local v0, "b":I return v0 .end method

JVM DVM

int a

int b

return b

b = a + 10int a

int breturn b

b = a + 10

Synchronized

39

public synchronized int foo(int a) { int b; b = a + 10; return b; }

public int foo(int a) { synchronized (this) { int b; b = a + 10; return b; }}

Bytecode synchronized method

40

public synchronized foo(I)I L0 LINENUMBER 34 L0 ILOAD 1 BIPUSH 10 IADD ISTORE 2 L1 LINENUMBER 35 L1 ILOAD 2 IRETURN L2 LOCALVARIABLE this Lgenerator/android/TestJava; L0 L2 0 LOCALVARIABLE a I L0 L2 1 LOCALVARIABLE b I L1 L2 2 MAXSTACK = 2 MAXLOCALS = 3

.method public declared-synchronized foo(I)I .registers 3 .param p1, "a" # I .prologue .line 21 monitor-enter p0 add-int/lit8 v0, p1, 0xa .line 22 .local v0, "b":I monitor-exit p0 return v0.end method

JVM DVM

b = a + 10

Synchronized block

41

public foo(I)I TRYCATCHBLOCK L0 L1 L2 null TRYCATCHBLOCK L2 L3 L2 null L4 LINENUMBER 10 L4 ALOAD 0 DUP ASTORE 2 MONITORENTER L0 //business logic L5 LINENUMBER 13 L5 ILOAD 3 ALOAD 2 MONITOREXIT L1 IRETURN L2 LINENUMBER 14 L2 FRAME FULL [generator/android/TestJava I java/lang/Object] [java/lang/Throwable] ASTORE 4 ALOAD 2 MONITOREXIT L3 ALOAD 4 ATHROW L6 LOCALVARIABLE b I L5 L2 3 LOCALVARIABLE this Lgenerator/android/TestJava; L4 L6 0 LOCALVARIABLE a I L4 L6 1 MAXSTACK = 2 MAXLOCALS = 5

.method public foo(I)I //initialization monitor-enter p0 //business logic :try_start_3 monitor-exit p0 return v0 .line 16 :catchall_5 move-exception v1 monitor-exit p0 :try_end_7 .catchall {:try_start_3 .. :try_end_7} :catchall_5 throw v1.end method

JVM DVM

Synchronized block – проще говоря

42

Monitor.enter() Throwable stored = null try{ businessLogic() } catch(Throwable e){ stored = e } Monitor.exit() if(stored != null) throw stored

return

JVM DVM

DVM synchronized method div

43

.method public final declared-synchronized fooDangerous(I)I .registers 4 .param p1, "a" # I .prologue .line 27 monitor-enter p0 :try_start_1 div-int/lit8 v0, p1, 0xa :try_end_3 .catchall {:try_start_1 .. :try_end_3} :catchall_5 .line 28 .local v0, "b":I monitor-exit p0 return v0 .line 27 .end local v0 # "b":I :catchall_5 move-exception v1 monitor-exit p0 throw v1.end method

.method public declared-synchronized foo(I)I .registers 3 .param p1, "a" # I .prologue .line 21 monitor-enter p0 add-int/lit8 v0, p1, 0xa .line 22 .local v0, "b":I monitor-exit p0 return v0.end method

b = a / 10b = a + 10

DMV synchronized method try-catch

44

• Вызов метода • Создание объекта • Деление целых чисел • Бросок исключения • Каст • Изменение поля класса • Загрузка класса

Итоги & QA - IV

45

• Байткод dalvik отличается от JVM • Не все флаги методов работают так же • Есть оптимизация в зависимости от опкодов

DVM bytecode

Links

46

• https://www.cs.umd.edu/~pugh/java/memoryModel/jsr133.pdf JSR 133

• http://shipilev.net/blog/2014/jmm-pragmatics/ Очень крутое объяснение JMM

• http://developer.android.com/intl/ru/training/articles/smp.html Гайд по MM в Android

• http://gee.cs.oswego.edu/dl/jmm/cookbook.html JMM для авторов компиляторов

• http://jcip.net/ Отличная книга про JMM

Спасибо за внимание!

[email protected]