Slide 1

Slide 1 text

Многопоточное программирование это СЛОЖНО Дмитрий Вязеленко @ Joker 2015 1

Slide 2

Slide 2 text

2 About me • Senior Software Engineer @ Sowatec AG, Switzerland • Disorganizer at JCrete Unconference, www.jcrete.org • Contacts: vyazelenko.com, @DVyazelenko

Slide 3

Slide 3 text

3 Содержание • Ошибаются все • Халява кончилась • Многопоточное программирование это СЛОЖНО • И как нам с этим жить

Slide 4

Slide 4 text

Ошибаются все 4

Slide 5

Slide 5 text

5

Slide 6

Slide 6 text

Haswell TSX bug 6 http://techreport.com/news/26911/errata-prompts-intel-to-disable-tsx-in-haswell-early-broadwell-cpus

Slide 7

Slide 7 text

7

Slide 8

Slide 8 text

Linux futex bug https://groups.google.com/forum/#!topic/mechanical-sympathy/QbmpZxp6C64 8

Slide 9

Slide 9 text

9

Slide 10

Slide 10 text

HotSpot optimization bug 10 public void think() { while (true) { if (checkInterruptedStatus()) break; } System.out.println("We're done thinking"); } private boolean checkInterruptedStatus() { return Thread.currentThread().isInterrupted(); } http://cs.oswego.edu/pipermail/concurrency-interest/2012-November/010184.html http://bugs.java.com/bugdatabase/view_bug.do?bug_id=8003135

Slide 11

Slide 11 text

11 https://twitter.com/mjpt777/status/619093423723782144

Slide 12

Slide 12 text

Халява кончилась 12

Slide 13

Slide 13 text

13 http://www.gotw.ca/publications/concurrency-ddj.htm

Slide 14

Slide 14 text

14 https://en.wikipedia.org/wiki/Amdahl%27s_law

Slide 15

Slide 15 text

15 http://www.perfdynamics.com/Manifesto/USLscalability.html C = capacity or throughput N = number of processors α = contention penalty β = coherence penalty

Slide 16

Slide 16 text

16 http://gotocon.com/dl/goto-cph-sept-2014/slides/ MartinThompson_RespondingInATimelyMannerMicrosecondsInHFTOrMillisecondsInWebAppsItsAllTheTheSameDesignPrinciples.pdf Source:

Slide 17

Slide 17 text

Многопоточное программирование это СЛОЖНО 17

Slide 18

Slide 18 text

18 public class Account { private long balance; public Account(long money) { this.balance = money; } public long balance() { return balance; } public void debit(long amount) { balance -= amount; } public void credit(long amount) { balance += amount; } }

Slide 19

Slide 19 text

19 public class Account { private final Lock lock = new ReentrantLock(); private long balance; public Account(long amount) { this.balance = amount; } public long balance() { lock.lock(); try { return balance; } finally { lock.unlock(); } } public void debit(long amount) { lock.lock(); try { balance -= amount; } finally { lock.unlock(); } } public void credit(long amount) { lock.lock(); try { balance += amount; } finally { lock.unlock(); } } }

Slide 20

Slide 20 text

20 public class AccountManager { public void transfer(Account src, Account dest, long amount) { if (src.balance() < amount) { throw new IllegalArgumentException("Insufficient funds!"); } src.debit(amount); dest.credit(amount); } }

Slide 21

Slide 21 text

20 public class AccountManager { public void transfer(Account src, Account dest, long amount) { if (src.balance() < amount) { throw new IllegalArgumentException("Insufficient funds!"); } src.debit(amount); dest.credit(amount); } }

Slide 22

Slide 22 text

21 public class Account { private final Lock lock = new ReentrantLock(); private long balance; public Account(long amount) { this.balance = amount; } public long balance() { lock.lock(); try { return balance; } finally { lock.unlock(); } } public void debit(long amount) { ... } public void credit(long amount) { ... } Lock getLock() { return lock; } }

Slide 23

Slide 23 text

22 public class AccountManager { public void transfer(Account src, Account dest, long amount) { Lock srcLock = src.getLock(); srcLock.lock(); try { Lock destLock = dest.getLock(); destLock.lock(); try { if (src.balance() < amount) { throw new IllegalArgumentException("Insufficient funds!"); } src.debit(amount); dest.credit(amount); } finally { destLock.unlock(); } } finally { srcLock.unlock(); } } }

Slide 24

Slide 24 text

23 public class TransferDeadlock { public static void main(String[] args) throws Exception { AccountManager manager = new AccountManager(); Account src = new Account(1000); Account dest = new Account(1000); Thread t1 = new Thread(() -> { for (int i = 0; i < 1000; i++) { manager.transfer(src, dest, 1); } }); Thread t2 = new Thread(() -> { for (int i = 0; i < 1000; i++) { manager.transfer(dest, src, 1); } }); t1.start(); t2.start(); t1.join(); t2.join(); } }

Slide 25

Slide 25 text

24 Found one Java-level deadlock: ============================= "Thread-1": waiting for ownable synchronizer 0x000000076abcced0, (a java.util.concurrent.locks.ReentrantLock$NonfairSync), which is held by "Thread-0" "Thread-0": waiting for ownable synchronizer 0x000000076abccf18, (a java.util.concurrent.locks.ReentrantLock$NonfairSync), which is held by "Thread-1" Java stack information for the threads listed above: =================================================== "Thread-1": at sun.misc.Unsafe.park(Native Method) - parking to wait for <0x000000076abcced0> (a java.util.concurrent.locks.ReentrantLock$NonfairSync) at java.util.concurrent.locks.LockSupport.park(LockSupport.java:175) at java.util.concurrent.locks.AbstractQueuedSynchronizer.parkAndCheckInterrupt(AbstractQueuedSynchronizer.java:836) at java.util.concurrent.locks.AbstractQueuedSynchronizer.acquireQueued(AbstractQueuedSynchronizer.java:870) at java.util.concurrent.locks.AbstractQueuedSynchronizer.acquire(AbstractQueuedSynchronizer.java:1199) at java.util.concurrent.locks.ReentrantLock$NonfairSync.lock(ReentrantLock.java:209) at java.util.concurrent.locks.ReentrantLock.lock(ReentrantLock.java:285) at com.vyazelenko.AccountManager.transfer(AccountManager.java:11) at com.vyazelenko.TransferDeadlock.lambda$main$1(TransferDeadlock.java:16) at com.vyazelenko.TransferDeadlock$$Lambda$2/363771819.run(Unknown Source) at java.lang.Thread.run(Thread.java:745) "Thread-0": at sun.misc.Unsafe.park(Native Method) - parking to wait for <0x000000076abccf18> (a java.util.concurrent.locks.ReentrantLock$NonfairSync) at java.util.concurrent.locks.LockSupport.park(LockSupport.java:175) at java.util.concurrent.locks.AbstractQueuedSynchronizer.parkAndCheckInterrupt(AbstractQueuedSynchronizer.java:836) at java.util.concurrent.locks.AbstractQueuedSynchronizer.acquireQueued(AbstractQueuedSynchronizer.java:870) at java.util.concurrent.locks.AbstractQueuedSynchronizer.acquire(AbstractQueuedSynchronizer.java:1199) at java.util.concurrent.locks.ReentrantLock$NonfairSync.lock(ReentrantLock.java:209) at java.util.concurrent.locks.ReentrantLock.lock(ReentrantLock.java:285) at com.vyazelenko.AccountManager.transfer(AccountManager.java:11) at com.vyazelenko.TransferDeadlock.lambda$main$0(TransferDeadlock.java:11) at com.vyazelenko.TransferDeadlock$$Lambda$1/668386784.run(Unknown Source) at java.lang.Thread.run(Thread.java:745) Found 1 deadlock.

Slide 26

Slide 26 text

25

Slide 27

Slide 27 text

26 public class Account { private final Lock lock = new ReentrantLock(); private final int accountNo; private long balance; public Account(long money, int accountNo) { this.balance = money; this.accountNo = accountNo; } public long balance() { ... } public void debit(long money) { ... } public void credit(long money) { ... } Lock getLock() { return lock; } public int getAccountNo() { return accountNo; } }

Slide 28

Slide 28 text

27 public class AccountManager { public void transfer(Account src, Account dest, long amount) { Lock srcLock = src.getLock(); Lock destLock = dest.getLock(); if (src.getAccountNo() > dest.getAccountNo()) { srcLock = dest.getLock(); destLock = src.getLock(); } srcLock.lock(); try { destLock.lock(); try { if (src.balance() < amount) { throw new IllegalArgumentException("Insufficient funds!"); } src.debit(amount); dest.credit(amount); } finally { destLock.unlock(); } } finally { srcLock.unlock(); } } }

Slide 29

Slide 29 text

28 http://www.amazon.com/Java-Concurrency-Practice-Brian-Goetz/dp/0321349601/ref=sr_1_1? s=books&ie=UTF8&qid=1445075658&sr=1-1&keywords=Java+Concurrency+in+Practice

Slide 30

Slide 30 text

29 http://www.jconcurrent.com/

Slide 31

Slide 31 text

30

Slide 32

Slide 32 text

И как нам с этим жить? 31

Slide 33

Slide 33 text

Пишите однопоточные приложения 32

Slide 34

Slide 34 text

33 http://www.frankmcsherry.org/graph/scalability/cost/2015/01/15/COST.html Маштабируемость! Но какой ценой?

Slide 35

Slide 35 text

33 http://www.frankmcsherry.org/graph/scalability/cost/2015/01/15/COST.html Маштабируемость! Но какой ценой?

Slide 36

Slide 36 text

Pipelining 34 S1 S2 S3

Slide 37

Slide 37 text

Message passing concurrency 35 • Communicating sequential processes (Go) • Actor Model (Akka, Erlang)

Slide 38

Slide 38 text

Message passing concurrency 35 • Communicating sequential processes (Go) • Actor Model (Akka, Erlang) Don't communicate by sharing memory; share memory by communicating.

Slide 39

Slide 39 text

Go Channels 36 https://gobyexample.com/channels

Slide 40

Slide 40 text

Akka example 37 http://doc.akka.io/docs/akka/2.0.2/intro/getting-started-first-java.html

Slide 41

Slide 41 text

Ссылки • The Free Lunch Is Over: A Fundamental Turn Toward Concurrency in Software (http://www.gotw.ca/publications/concurrency-ddj.htm) • Amdahl's law (https://en.wikipedia.org/wiki/Amdahl%27s_law) • How to Quantify Scalability (http://www.perfdynamics.com/Manifesto/ USLscalability.html) • Java Concurrency in Practice (http://www.amazon.com/Java-Concurrency- Practice-Brian-Goetz/dp/0321349601/ref=sr_1_1? s=books&ie=UTF8&qid=1445075658&sr=1-1&keywords=Java+Concurrency +in+Practice) • The Art of Multiprocessor Programming (http://www.amazon.com/Art- Multiprocessor-Programming-Revised-Reprint/dp/0123973376/ref=sr_1_5? s=books&ie=UTF8&qid=1445075883&sr=1-5&keywords=concurrent +programming) 38

Slide 42

Slide 42 text

Ссылки • Java Concurrent Animated (http://www.jconcurrent.com/) • Scalability! But at what COST? (http:// www.frankmcsherry.org/graph/scalability/cost/2015/01/15/ COST.html) • http://mechanical-sympathy.blogspot.ru/ • https://groups.google.com/forum/#!forum/mechanical- sympathy • Concurrency-interest mailing list (http:// altair.cs.oswego.edu/mailman/listinfo/concurrency-interest) 39

Slide 43

Slide 43 text

40 Questions? @DVyazelenko