Slide 1

Slide 1 text

@jessewilson https://github.com/swankjesse/concurrency Coordinating Space and Time

Slide 2

Slide 2 text

Motivation • We want it all: • Fast, responsive apps • Simple, correct code • Exploring the underlying systems should help

Slide 3

Slide 3 text

Plan • Why concurrency is difficult? • All the concurrency APIs • A recipe for success

Slide 4

Slide 4 text

Why is Concurrency Difficult? PART 1

Slide 5

Slide 5 text

Model vs. Machine • Code is abstract • Computers are concrete • Everything is particles bumping particles

Slide 6

Slide 6 text

iFixit, https://www.ifixit.com/Teardown/Google+Pixel+XL+Teardown/71237

Slide 7

Slide 7 text

iFixit, https://www.ifixit.com/Teardown/Google+Pixel+XL+Teardown/71237

Slide 8

Slide 8 text

iFixit, https://www.ifixit.com/Teardown/Google+Pixel+XL+Teardown/71237

Slide 9

Slide 9 text

No content

Slide 10

Slide 10 text

• Central Processing Unit • Where your code runs • For example, if your code wants to add a pair of integers, the CPU includes a mechanism that does that

Slide 11

Slide 11 text

• Random-Access Memory • Where your data is • When the CPU runs
 new ArrayList()
 an area of memory is assigned to hold the corresponding object

Slide 12

Slide 12 text

CPU Registers • The CPU has 31 memory slots called registers • All input to the CPU must be loaded into a register • All output from the CPU is emitted to a register CPU register value 0 1 1 200 2 0 3 2147483647 4 32768 5 2 6 2147483646 7 300 8 9223372030 9 7483600 27 10 28 65535 29 1 30 0 . . .

Slide 13

Slide 13 text

offset value 0 200 8 0 16 2147483647 24 32768 32 2 40 2147483646 48 300 56 9223372030 64 7483600 72 8675309 4,294,967,264 65535 4,294,967,272 1 4,294,967,280 9223372030 4,294,967,288 20 RAM • Just a contiguous range of 4 billion bytes • Read and write, and that’s it RAM . . .

Slide 14

Slide 14 text

Example: Pixel Counter blueCount 1 redCount 2

Slide 15

Slide 15 text

public class PixelCounter {
 public static final int BLUE = 100;
 public static final int RED = 200;
 
 int blueCount;
 int redCount;
 
 void count(int[] pixels) {
 for (int i = 0; i < pixels.length; i++) {
 int pixel = pixels[i];
 if (pixel == BLUE) blueCount++; else if (pixel == RED) redCount++;
 }
 } }

Slide 16

Slide 16 text

public static void main(String[] args) {
 int[] pixels = new int[3]; pixels[0] = RED; // 200
 pixels[1] = RED; // 200
 pixels[2] = BLUE; // 100
 
 PixelCounter pixelCounter = new PixelCounter();
 pixelCounter.count(pixels);
 }a

Slide 17

Slide 17 text

public static void main(String[] args) {
 int[] pixels = new int[3]; pixels[0] = RED; // 200
 pixels[1] = RED; // 200
 pixels[2] = BLUE; // 100
 
 PixelCounter pixelCounter = new PixelCounter();
 pixelCounter.count(pixels);
 }a RAM offset name value 1000 type int[].class 1008 length 3 1016 0 200 1024 1 200 1032 2 100 1040 1048 type PixelCounter.class 1056 blueCount 0 1064 redCount 0

Slide 18

Slide 18 text

void count(int[] pixels) {
 for (int i = 0; i < pixels.length; i++) {
 int pixel = pixels[i];
 if (pixel == BLUE) blueCount++;
 else if (pixel == RED) redCount++;
 }x }y CPU RAM register name value 0 BLUE 100 1 RED 200 2 this 1048 3 pixels 1000 4 5 6 7 8 offset name value 1000 type int[].class 1008 length 3 1016 0 200 1024 1 200 1032 2 100 1040 1048 type PixelCounter.class 1056 blueCount 0 1064 redCount 0

Slide 19

Slide 19 text

void count(int[] pixels) {
 for (int i = 0; i < pixels.length; i++) {
 int pixel = pixels[i];
 if (pixel == BLUE) blueCount++;
 else if (pixel == RED) redCount++;
 }x }y CPU RAM register name value 0 BLUE 100 1 RED 200 2 this 1048 3 pixels 1000 4 5 6 7 8 offset name value 1000 type int[].class 1008 length 3 1016 0 200 1024 1 200 1032 2 100 1040 1048 type PixelCounter.class 1056 blueCount 0 1064 redCount 0

Slide 20

Slide 20 text

void count(int[] pixels) {
 for (int i = 0; i < pixels.length; i++) {
 int pixel = pixels[i];
 if (pixel == BLUE) blueCount++;
 else if (pixel == RED) redCount++;
 }x }y CPU RAM register name value 0 BLUE 100 1 RED 200 2 this 1048 3 pixels 1000 4 i 0 5 6 7 8 offset name value 1000 type int[].class 1008 length 3 1016 0 200 1024 1 200 1032 2 100 1040 1048 type PixelCounter.class 1056 blueCount 0 1064 redCount 0

Slide 21

Slide 21 text

void count(int[] pixels) {
 for (int i = 0; i < pixels.length; i++) {
 int pixel = pixels[i];
 if (pixel == BLUE) blueCount++;
 else if (pixel == RED) redCount++;
 }x }y CPU RAM register name value 0 BLUE 100 1 RED 200 2 this 1048 3 pixels 1000 4 i 0 5 6 7 8 offset name value 1000 type int[].class 1008 length 3 1016 0 200 1024 1 200 1032 2 100 1040 1048 type PixelCounter.class 1056 blueCount 0 1064 redCount 0

Slide 22

Slide 22 text

void count(int[] pixels) {
 for (int i = 0; i < pixels.length; i++) {
 int pixel = pixels[i];
 if (pixel == BLUE) blueCount++;
 else if (pixel == RED) redCount++;
 }x }y CPU RAM register name value 0 BLUE 100 1 RED 200 2 this 1048 3 pixels 1000 4 i 0 5 6 7 8 offset name value 1000 type int[].class 1008 length 3 1016 0 200 1024 1 200 1032 2 100 1040 1048 type PixelCounter.class 1056 blueCount 0 1064 redCount 0

Slide 23

Slide 23 text

void count(int[] pixels) {
 for (int i = 0; i < pixels.length; i++) {
 int pixel = pixels[i];
 if (pixel == BLUE) blueCount++;
 else if (pixel == RED) redCount++;
 }x }y CPU RAM register name value 0 BLUE 100 1 RED 200 2 this 1048 3 pixels 1000 4 i 0 5 6 7 8 offset name value 1000 type int[].class 1008 length 3 1016 0 200 1024 1 200 1032 2 100 1040 1048 type PixelCounter.class 1056 blueCount 0 1064 redCount 0 3 pixels.length

Slide 24

Slide 24 text

void count(int[] pixels) {
 for (int i = 0; i < pixels.length; i++) {
 int pixel = pixels[i];
 if (pixel == BLUE) blueCount++;
 else if (pixel == RED) redCount++;
 }x }y CPU RAM register name value 0 BLUE 100 1 RED 200 2 this 1048 3 pixels 1000 4 i 0 5 pixels.length 3 6 7 8 offset name value 1000 type int[].class 1008 length 3 1016 0 200 1024 1 200 1032 2 100 1040 1048 type PixelCounter.class 1056 blueCount 0 1064 redCount 0

Slide 25

Slide 25 text

void count(int[] pixels) {
 for (int i = 0; i < pixels.length; i++) {
 int pixel = pixels[i];
 if (pixel == BLUE) blueCount++;
 else if (pixel == RED) redCount++;
 }x }y CPU RAM register name value 0 BLUE 100 1 RED 200 2 this 1048 3 pixels 1000 4 i 0 5 pixels.length 3 6 7 8 offset name value 1000 type int[].class 1008 length 3 1016 0 200 1024 1 200 1032 2 100 1040 1048 type PixelCounter.class 1056 blueCount 0 1064 redCount 0 <

Slide 26

Slide 26 text

void count(int[] pixels) {
 for (int i = 0; i < pixels.length; i++) {
 int pixel = pixels[i];
 if (pixel == BLUE) blueCount++;
 else if (pixel == RED) redCount++;
 }x }y CPU RAM register name value 0 BLUE 100 1 RED 200 2 this 1048 3 pixels 1000 4 i 0 5 pixels.length 3 6 7 8 offset name value 1000 type int[].class 1008 length 3 1016 0 200 1024 1 200 1032 2 100 1040 1048 type PixelCounter.class 1056 blueCount 0 1064 redCount 0

Slide 27

Slide 27 text

void count(int[] pixels) {
 for (int i = 0; i < pixels.length; i++) {
 int pixel = pixels[i];
 if (pixel == BLUE) blueCount++;
 else if (pixel == RED) redCount++;
 }x }y CPU RAM register name value 0 BLUE 100 1 RED 200 2 this 1048 3 pixels 1000 4 i 0 5 pixels.length 3 6 7 8 offset name value 1000 type int[].class 1008 length 3 1016 0 200 1024 1 200 1032 2 100 1040 1048 type PixelCounter.class 1056 blueCount 0 1064 redCount 0

Slide 28

Slide 28 text

void count(int[] pixels) {
 for (int i = 0; i < pixels.length; i++) {
 int pixel = pixels[i];
 if (pixel == BLUE) blueCount++;
 else if (pixel == RED) redCount++;
 }x }y CPU RAM register name value 0 BLUE 100 1 RED 200 2 this 1048 3 pixels 1000 4 i 0 5 pixels.length 3 6 7 8 offset name value 1000 type int[].class 1008 length 3 1016 0 200 1024 1 200 1032 2 100 1040 1048 type PixelCounter.class 1056 blueCount 0 1064 redCount 0 200 pixel

Slide 29

Slide 29 text

void count(int[] pixels) {
 for (int i = 0; i < pixels.length; i++) {
 int pixel = pixels[i];
 if (pixel == BLUE) blueCount++;
 else if (pixel == RED) redCount++;
 }x }y CPU RAM register name value 0 BLUE 100 1 RED 200 2 this 1048 3 pixels 1000 4 i 0 5 pixels.length 3 6 pixel 200 7 8 offset name value 1000 type int[].class 1008 length 3 1016 0 200 1024 1 200 1032 2 100 1040 1048 type PixelCounter.class 1056 blueCount 0 1064 redCount 0

Slide 30

Slide 30 text

void count(int[] pixels) {
 for (int i = 0; i < pixels.length; i++) {
 int pixel = pixels[i];
 if (pixel == BLUE) blueCount++;
 else if (pixel == RED) redCount++;
 }x }y CPU RAM register name value 0 BLUE 100 1 RED 200 2 this 1048 3 pixels 1000 4 i 0 5 pixels.length 3 6 pixel 200 7 8 offset name value 1000 type int[].class 1008 length 3 1016 0 200 1024 1 200 1032 2 100 1040 1048 type PixelCounter.class 1056 blueCount 0 1064 redCount 0

Slide 31

Slide 31 text

void count(int[] pixels) {
 for (int i = 0; i < pixels.length; i++) {
 int pixel = pixels[i];
 if (pixel == BLUE) blueCount++;
 else if (pixel == RED) redCount++;
 }x }y CPU RAM register name value 0 BLUE 100 1 RED 200 2 this 1048 3 pixels 1000 4 i 0 5 pixels.length 3 6 pixel 200 7 8 offset name value 1000 type int[].class 1008 length 3 1016 0 200 1024 1 200 1032 2 100 1040 1048 type PixelCounter.class 1056 blueCount 0 1064 redCount 0 ==

Slide 32

Slide 32 text

void count(int[] pixels) {
 for (int i = 0; i < pixels.length; i++) {
 int pixel = pixels[i];
 if (pixel == BLUE) blueCount++;
 else if (pixel == RED) redCount++;
 }x }y CPU RAM register name value 0 BLUE 100 1 RED 200 2 this 1048 3 pixels 1000 4 i 0 5 pixels.length 3 6 pixel 200 7 8 offset name value 1000 type int[].class 1008 length 3 1016 0 200 1024 1 200 1032 2 100 1040 1048 type PixelCounter.class 1056 blueCount 0 1064 redCount 0

Slide 33

Slide 33 text

void count(int[] pixels) {
 for (int i = 0; i < pixels.length; i++) {
 int pixel = pixels[i];
 if (pixel == BLUE) blueCount++;
 else if (pixel == RED) redCount++;
 }x }y CPU RAM register name value 0 BLUE 100 1 RED 200 2 this 1048 3 pixels 1000 4 i 0 5 pixels.length 3 6 pixel 200 7 8 offset name value 1000 type int[].class 1008 length 3 1016 0 200 1024 1 200 1032 2 100 1040 1048 type PixelCounter.class 1056 blueCount 0 1064 redCount 0

Slide 34

Slide 34 text

void count(int[] pixels) {
 for (int i = 0; i < pixels.length; i++) {
 int pixel = pixels[i];
 if (pixel == BLUE) blueCount++;
 else if (pixel == RED) redCount++;
 }x }y CPU RAM register name value 0 BLUE 100 1 RED 200 2 this 1048 3 pixels 1000 4 i 0 5 pixels.length 3 6 pixel 200 7 8 offset name value 1000 type int[].class 1008 length 3 1016 0 200 1024 1 200 1032 2 100 1040 1048 type PixelCounter.class 1056 blueCount 0 1064 redCount 0 ==

Slide 35

Slide 35 text

void count(int[] pixels) {
 for (int i = 0; i < pixels.length; i++) {
 int pixel = pixels[i];
 if (pixel == BLUE) blueCount++;
 else if (pixel == RED) redCount++;
 }x }y CPU RAM register name value 0 BLUE 100 1 RED 200 2 this 1048 3 pixels 1000 4 i 0 5 pixels.length 3 6 pixel 200 7 8 offset name value 1000 type int[].class 1008 length 3 1016 0 200 1024 1 200 1032 2 100 1040 1048 type PixelCounter.class 1056 blueCount 0 1064 redCount 0

Slide 36

Slide 36 text

void count(int[] pixels) {
 for (int i = 0; i < pixels.length; i++) {
 int pixel = pixels[i];
 if (pixel == BLUE) blueCount++;
 else if (pixel == RED) redCount++;
 }x }y CPU RAM register name value 0 BLUE 100 1 RED 200 2 this 1048 3 pixels 1000 4 i 0 5 pixels.length 3 6 pixel 200 7 8 offset name value 1000 type int[].class 1008 length 3 1016 0 200 1024 1 200 1032 2 100 1040 1048 type PixelCounter.class 1056 blueCount 0 1064 redCount 0

Slide 37

Slide 37 text

void count(int[] pixels) {
 for (int i = 0; i < pixels.length; i++) {
 int pixel = pixels[i];
 if (pixel == BLUE) blueCount++;
 else if (pixel == RED) redCount++;
 }x }y CPU RAM register name value 0 BLUE 100 1 RED 200 2 this 1048 3 pixels 1000 4 i 0 5 pixels.length 3 6 pixel 200 7 8 offset name value 1000 type int[].class 1008 length 3 1016 0 200 1024 1 200 1032 2 100 1040 1048 type PixelCounter.class 1056 blueCount 0 1064 redCount 0 0 redCount

Slide 38

Slide 38 text

void count(int[] pixels) {
 for (int i = 0; i < pixels.length; i++) {
 int pixel = pixels[i];
 if (pixel == BLUE) blueCount++;
 else if (pixel == RED) redCount++;
 }x }y CPU RAM register name value 0 BLUE 100 1 RED 200 2 this 1048 3 pixels 1000 4 i 0 5 pixels.length 3 6 pixel 200 7 redCount 0 8 offset name value 1000 type int[].class 1008 length 3 1016 0 200 1024 1 200 1032 2 100 1040 1048 type PixelCounter.class 1056 blueCount 0 1064 redCount 0

Slide 39

Slide 39 text

void count(int[] pixels) {
 for (int i = 0; i < pixels.length; i++) {
 int pixel = pixels[i];
 if (pixel == BLUE) blueCount++;
 else if (pixel == RED) redCount++;
 }x }y CPU RAM register name value 0 BLUE 100 1 RED 200 2 this 1048 3 pixels 1000 4 i 0 5 pixels.length 3 6 pixel 200 7 redCount 1 8 offset name value 1000 type int[].class 1008 length 3 1016 0 200 1024 1 200 1032 2 100 1040 1048 type PixelCounter.class 1056 blueCount 0 1064 redCount 0 ++

Slide 40

Slide 40 text

void count(int[] pixels) {
 for (int i = 0; i < pixels.length; i++) {
 int pixel = pixels[i];
 if (pixel == BLUE) blueCount++;
 else if (pixel == RED) redCount++;
 }x }y CPU RAM register name value 0 BLUE 100 1 RED 200 2 this 1048 3 pixels 1000 4 i 0 5 pixels.length 3 6 pixel 200 7 redCount 1 8 offset name value 1000 type int[].class 1008 length 3 1016 0 200 1024 1 200 1032 2 100 1040 1048 type PixelCounter.class 1056 blueCount 0 1064 redCount 0

Slide 41

Slide 41 text

void count(int[] pixels) {
 for (int i = 0; i < pixels.length; i++) {
 int pixel = pixels[i];
 if (pixel == BLUE) blueCount++;
 else if (pixel == RED) redCount++;
 }x }y CPU RAM register name value 0 BLUE 100 1 RED 200 2 this 1048 3 pixels 1000 4 i 0 5 pixels.length 3 6 pixel 200 7 redCount 1 8 offset name value 1000 type int[].class 1008 length 3 1016 0 200 1024 1 200 1032 2 100 1040 1048 type PixelCounter.class 1056 blueCount 0 1064 redCount 1 0

Slide 42

Slide 42 text

void count(int[] pixels) {
 for (int i = 0; i < pixels.length; i++) {
 int pixel = pixels[i];
 if (pixel == BLUE) blueCount++;
 else if (pixel == RED) redCount++;
 }x }y CPU RAM register name value 0 BLUE 100 1 RED 200 2 this 1048 3 pixels 1000 4 i 0 5 pixels.length 3 6 pixel 200 7 redCount 1 8 offset name value 1000 type int[].class 1008 length 3 1016 0 200 1024 1 200 1032 2 100 1040 1048 type PixelCounter.class 1056 blueCount 0 1064 redCount 1

Slide 43

Slide 43 text

void count(int[] pixels) {
 for (int i = 0; i < pixels.length; i++) {
 int pixel = pixels[i];
 if (pixel == BLUE) blueCount++;
 else if (pixel == RED) redCount++;
 }x }y CPU RAM register name value 0 BLUE 100 1 RED 200 2 this 1048 3 pixels 1000 4 i 0 5 pixels.length 3 6 pixel 200 7 redCount 1 8 offset name value 1000 type int[].class 1008 length 3 1016 0 200 1024 1 200 1032 2 100 1040 1048 type PixelCounter.class 1056 blueCount 0 1064 redCount 1

Slide 44

Slide 44 text

void count(int[] pixels) {
 for (int i = 0; i < pixels.length; i++) {
 int pixel = pixels[i];
 if (pixel == BLUE) blueCount++;
 else if (pixel == RED) redCount++;
 }x }y CPU RAM register name value 0 BLUE 100 1 RED 200 2 this 1048 3 pixels 1000 4 i 1 5 pixels.length 3 6 pixel 200 7 redCount 1 8 offset name value 1000 type int[].class 1008 length 3 1016 0 200 1024 1 200 1032 2 100 1040 1048 type PixelCounter.class 1056 blueCount 0 1064 redCount 1 ++

Slide 45

Slide 45 text

void count(int[] pixels) {
 for (int i = 0; i < pixels.length; i++) {
 int pixel = pixels[i];
 if (pixel == BLUE) blueCount++;
 else if (pixel == RED) redCount++;
 }x }y CPU RAM register name value 0 BLUE 100 1 RED 200 2 this 1048 3 pixels 1000 4 i 1 5 pixels.length 3 6 pixel 200 7 redCount 1 8 offset name value 1000 type int[].class 1008 length 3 1016 0 200 1024 1 200 1032 2 100 1040 1048 type PixelCounter.class 1056 blueCount 0 1064 redCount 1

Slide 46

Slide 46 text

void count(int[] pixels) {
 for (int i = 0; i < pixels.length; i++) {
 int pixel = pixels[i];
 if (pixel == BLUE) blueCount++;
 else if (pixel == RED) redCount++;
 }x }y CPU RAM register name value 0 BLUE 100 1 RED 200 2 this 1048 3 pixels 1000 4 i 1 5 pixels.length 3 6 pixel 200 7 redCount 1 8 offset name value 1000 type int[].class 1008 length 3 1016 0 200 1024 1 200 1032 2 100 1040 1048 type PixelCounter.class 1056 blueCount 0 1064 redCount 1

Slide 47

Slide 47 text

void count(int[] pixels) {
 for (int i = 0; i < pixels.length; i++) {
 int pixel = pixels[i];
 if (pixel == BLUE) blueCount++;
 else if (pixel == RED) redCount++;
 }x }y CPU RAM register name value 0 BLUE 100 1 RED 200 2 this 1048 3 pixels 1000 4 i 1 5 pixels.length 6 pixel 200 7 redCount 1 8 offset name value 1000 type int[].class 1008 length 3 1016 0 200 1024 1 200 1032 2 100 1040 1048 type PixelCounter.class 1056 blueCount 0 1064 redCount 1 3 3

Slide 48

Slide 48 text

void count(int[] pixels) {
 for (int i = 0; i < pixels.length; i++) {
 int pixel = pixels[i];
 if (pixel == BLUE) blueCount++;
 else if (pixel == RED) redCount++;
 }x }y CPU RAM register name value 0 BLUE 100 1 RED 200 2 this 1048 3 pixels 1000 4 i 1 5 pixels.length 3 6 pixel 200 7 redCount 1 8 offset name value 1000 type int[].class 1008 length 3 1016 0 200 1024 1 200 1032 2 100 1040 1048 type PixelCounter.class 1056 blueCount 0 1064 redCount 1

Slide 49

Slide 49 text

void count(int[] pixels) {
 for (int i = 0; i < pixels.length; i++) {
 int pixel = pixels[i];
 if (pixel == BLUE) blueCount++;
 else if (pixel == RED) redCount++;
 }x }y CPU RAM register name value 0 BLUE 100 1 RED 200 2 this 1048 3 pixels 1000 4 i 1 5 pixels.length 3 6 pixel 200 7 redCount 1 8 offset name value 1000 type int[].class 1008 length 3 1016 0 200 1024 1 200 1032 2 100 1040 1048 type PixelCounter.class 1056 blueCount 0 1064 redCount 1 <

Slide 50

Slide 50 text

void count(int[] pixels) {
 for (int i = 0; i < pixels.length; i++) {
 int pixel = pixels[i];
 if (pixel == BLUE) blueCount++;
 else if (pixel == RED) redCount++;
 }x }y CPU RAM register name value 0 BLUE 100 1 RED 200 2 this 1048 3 pixels 1000 4 i 1 5 pixels.length 3 6 pixel 200 7 redCount 1 8 offset name value 1000 type int[].class 1008 length 3 1016 0 200 1024 1 200 1032 2 100 1040 1048 type PixelCounter.class 1056 blueCount 0 1064 redCount 1

Slide 51

Slide 51 text

void count(int[] pixels) {
 for (int i = 0; i < pixels.length; i++) {
 int pixel = pixels[i];
 if (pixel == BLUE) blueCount++;
 else if (pixel == RED) redCount++;
 }x }y CPU RAM register name value 0 BLUE 100 1 RED 200 2 this 1048 3 pixels 1000 4 i 1 5 pixels.length 3 6 pixel 200 7 redCount 1 8 offset name value 1000 type int[].class 1008 length 3 1016 0 200 1024 1 200 1032 2 100 1040 1048 type PixelCounter.class 1056 blueCount 0 1064 redCount 1

Slide 52

Slide 52 text

void count(int[] pixels) {
 for (int i = 0; i < pixels.length; i++) {
 int pixel = pixels[i];
 if (pixel == BLUE) blueCount++;
 else if (pixel == RED) redCount++;
 }x }y CPU RAM register name value 0 BLUE 100 1 RED 200 2 this 1048 3 pixels 1000 4 i 1 5 pixels.length 3 6 pixel 7 redCount 1 8 offset name value 1000 type int[].class 1008 length 3 1016 0 200 1024 1 200 1032 2 100 1040 1048 type PixelCounter.class 1056 blueCount 0 1064 redCount 1 200 200

Slide 53

Slide 53 text

void count(int[] pixels) {
 for (int i = 0; i < pixels.length; i++) {
 int pixel = pixels[i];
 if (pixel == BLUE) blueCount++;
 else if (pixel == RED) redCount++;
 }x }y CPU RAM register name value 0 BLUE 100 1 RED 200 2 this 1048 3 pixels 1000 4 i 1 5 pixels.length 3 6 pixel 200 7 redCount 1 8 offset name value 1000 type int[].class 1008 length 3 1016 0 200 1024 1 200 1032 2 100 1040 1048 type PixelCounter.class 1056 blueCount 0 1064 redCount 1

Slide 54

Slide 54 text

void count(int[] pixels) {
 for (int i = 0; i < pixels.length; i++) {
 int pixel = pixels[i];
 if (pixel == BLUE) blueCount++;
 else if (pixel == RED) redCount++;
 }x }y CPU RAM register name value 0 BLUE 100 1 RED 200 2 this 1048 3 pixels 1000 4 i 1 5 pixels.length 3 6 pixel 200 7 redCount 1 8 offset name value 1000 type int[].class 1008 length 3 1016 0 200 1024 1 200 1032 2 100 1040 1048 type PixelCounter.class 1056 blueCount 0 1064 redCount 1

Slide 55

Slide 55 text

void count(int[] pixels) {
 for (int i = 0; i < pixels.length; i++) {
 int pixel = pixels[i];
 if (pixel == BLUE) blueCount++;
 else if (pixel == RED) redCount++;
 }x }y CPU RAM register name value 0 BLUE 100 1 RED 200 2 this 1048 3 pixels 1000 4 i 1 5 pixels.length 3 6 pixel 200 7 redCount 1 8 offset name value 1000 type int[].class 1008 length 3 1016 0 200 1024 1 200 1032 2 100 1040 1048 type PixelCounter.class 1056 blueCount 0 1064 redCount 1 ==

Slide 56

Slide 56 text

void count(int[] pixels) {
 for (int i = 0; i < pixels.length; i++) {
 int pixel = pixels[i];
 if (pixel == BLUE) blueCount++;
 else if (pixel == RED) redCount++;
 }x }y CPU RAM register name value 0 BLUE 100 1 RED 200 2 this 1048 3 pixels 1000 4 i 1 5 pixels.length 3 6 pixel 200 7 redCount 1 8 offset name value 1000 type int[].class 1008 length 3 1016 0 200 1024 1 200 1032 2 100 1040 1048 type PixelCounter.class 1056 blueCount 0 1064 redCount 1

Slide 57

Slide 57 text

void count(int[] pixels) {
 for (int i = 0; i < pixels.length; i++) {
 int pixel = pixels[i];
 if (pixel == BLUE) blueCount++;
 else if (pixel == RED) redCount++;
 }x }y CPU RAM register name value 0 BLUE 100 1 RED 200 2 this 1048 3 pixels 1000 4 i 1 5 pixels.length 3 6 pixel 200 7 redCount 1 8 offset name value 1000 type int[].class 1008 length 3 1016 0 200 1024 1 200 1032 2 100 1040 1048 type PixelCounter.class 1056 blueCount 0 1064 redCount 1

Slide 58

Slide 58 text

void count(int[] pixels) {
 for (int i = 0; i < pixels.length; i++) {
 int pixel = pixels[i];
 if (pixel == BLUE) blueCount++;
 else if (pixel == RED) redCount++;
 }x }y CPU RAM register name value 0 BLUE 100 1 RED 200 2 this 1048 3 pixels 1000 4 i 1 5 pixels.length 3 6 pixel 200 7 redCount 1 8 offset name value 1000 type int[].class 1008 length 3 1016 0 200 1024 1 200 1032 2 100 1040 1048 type PixelCounter.class 1056 blueCount 0 1064 redCount 1 ==

Slide 59

Slide 59 text

void count(int[] pixels) {
 for (int i = 0; i < pixels.length; i++) {
 int pixel = pixels[i];
 if (pixel == BLUE) blueCount++;
 else if (pixel == RED) redCount++;
 }x }y CPU RAM register name value 0 BLUE 100 1 RED 200 2 this 1048 3 pixels 1000 4 i 1 5 pixels.length 3 6 pixel 200 7 redCount 1 8 offset name value 1000 type int[].class 1008 length 3 1016 0 200 1024 1 200 1032 2 100 1040 1048 type PixelCounter.class 1056 blueCount 0 1064 redCount 1

Slide 60

Slide 60 text

void count(int[] pixels) {
 for (int i = 0; i < pixels.length; i++) {
 int pixel = pixels[i];
 if (pixel == BLUE) blueCount++;
 else if (pixel == RED) redCount++;
 }x }y CPU RAM register name value 0 BLUE 100 1 RED 200 2 this 1048 3 pixels 1000 4 i 1 5 pixels.length 3 6 pixel 200 7 redCount 1 8 offset name value 1000 type int[].class 1008 length 3 1016 0 200 1024 1 200 1032 2 100 1040 1048 type PixelCounter.class 1056 blueCount 0 1064 redCount 1

Slide 61

Slide 61 text

void count(int[] pixels) {
 for (int i = 0; i < pixels.length; i++) {
 int pixel = pixels[i];
 if (pixel == BLUE) blueCount++;
 else if (pixel == RED) redCount++;
 }x }y CPU RAM register name value 0 BLUE 100 1 RED 200 2 this 1048 3 pixels 1000 4 i 1 5 pixels.length 3 6 pixel 200 7 redCount 8 offset name value 1000 type int[].class 1008 length 3 1016 0 200 1024 1 200 1032 2 100 1040 1048 type PixelCounter.class 1056 blueCount 0 1064 redCount 1 1 1

Slide 62

Slide 62 text

void count(int[] pixels) {
 for (int i = 0; i < pixels.length; i++) {
 int pixel = pixels[i];
 if (pixel == BLUE) blueCount++;
 else if (pixel == RED) redCount++;
 }x }y CPU RAM register name value 0 BLUE 100 1 RED 200 2 this 1048 3 pixels 1000 4 i 1 5 pixels.length 3 6 pixel 200 7 redCount 1 8 offset name value 1000 type int[].class 1008 length 3 1016 0 200 1024 1 200 1032 2 100 1040 1048 type PixelCounter.class 1056 blueCount 0 1064 redCount 1

Slide 63

Slide 63 text

void count(int[] pixels) {
 for (int i = 0; i < pixels.length; i++) {
 int pixel = pixels[i];
 if (pixel == BLUE) blueCount++;
 else if (pixel == RED) redCount++;
 }x }y CPU RAM register name value 0 BLUE 100 1 RED 200 2 this 1048 3 pixels 1000 4 i 1 5 pixels.length 3 6 pixel 200 7 redCount 2 8 offset name value 1000 type int[].class 1008 length 3 1016 0 200 1024 1 200 1032 2 100 1040 1048 type PixelCounter.class 1056 blueCount 0 1064 redCount 1 ++

Slide 64

Slide 64 text

void count(int[] pixels) {
 for (int i = 0; i < pixels.length; i++) {
 int pixel = pixels[i];
 if (pixel == BLUE) blueCount++;
 else if (pixel == RED) redCount++;
 }x }y CPU RAM register name value 0 BLUE 100 1 RED 200 2 this 1048 3 pixels 1000 4 i 1 5 pixels.length 3 6 pixel 200 7 redCount 2 8 offset name value 1000 type int[].class 1008 length 3 1016 0 200 1024 1 200 1032 2 100 1040 1048 type PixelCounter.class 1056 blueCount 0 1064 redCount 1

Slide 65

Slide 65 text

void count(int[] pixels) {
 for (int i = 0; i < pixels.length; i++) {
 int pixel = pixels[i];
 if (pixel == BLUE) blueCount++;
 else if (pixel == RED) redCount++;
 }x }y CPU RAM register name value 0 BLUE 100 1 RED 200 2 this 1048 3 pixels 1000 4 i 1 5 pixels.length 3 6 pixel 200 7 redCount 2 8 offset name value 1000 type int[].class 1008 length 3 1016 0 200 1024 1 200 1032 2 100 1040 1048 type PixelCounter.class 1056 blueCount 0 1064 redCount 2 1

Slide 66

Slide 66 text

void count(int[] pixels) {
 for (int i = 0; i < pixels.length; i++) {
 int pixel = pixels[i];
 if (pixel == BLUE) blueCount++;
 else if (pixel == RED) redCount++;
 }x }y CPU RAM register name value 0 BLUE 100 1 RED 200 2 this 1048 3 pixels 1000 4 i 1 5 pixels.length 3 6 pixel 200 7 redCount 2 8 offset name value 1000 type int[].class 1008 length 3 1016 0 200 1024 1 200 1032 2 100 1040 1048 type PixelCounter.class 1056 blueCount 0 1064 redCount 2

Slide 67

Slide 67 text

void count(int[] pixels) {
 for (int i = 0; i < pixels.length; i++) {
 int pixel = pixels[i];
 if (pixel == BLUE) blueCount++;
 else if (pixel == RED) redCount++;
 }x }y CPU RAM register name value 0 BLUE 100 1 RED 200 2 this 1048 3 pixels 1000 4 i 1 5 pixels.length 3 6 pixel 200 7 redCount 2 8 offset name value 1000 type int[].class 1008 length 3 1016 0 200 1024 1 200 1032 2 100 1040 1048 type PixelCounter.class 1056 blueCount 0 1064 redCount 2

Slide 68

Slide 68 text

void count(int[] pixels) {
 for (int i = 0; i < pixels.length; i++) {
 int pixel = pixels[i];
 if (pixel == BLUE) blueCount++;
 else if (pixel == RED) redCount++;
 }x }y CPU RAM register name value 0 BLUE 100 1 RED 200 2 this 1048 3 pixels 1000 4 i 2 5 pixels.length 3 6 pixel 200 7 redCount 2 8 offset name value 1000 type int[].class 1008 length 3 1016 0 200 1024 1 200 1032 2 100 1040 1048 type PixelCounter.class 1056 blueCount 0 1064 redCount 2 ++

Slide 69

Slide 69 text

void count(int[] pixels) {
 for (int i = 0; i < pixels.length; i++) {
 int pixel = pixels[i];
 if (pixel == BLUE) blueCount++;
 else if (pixel == RED) redCount++;
 }x }y CPU RAM register name value 0 BLUE 100 1 RED 200 2 this 1048 3 pixels 1000 4 i 2 5 pixels.length 3 6 pixel 200 7 redCount 2 8 offset name value 1000 type int[].class 1008 length 3 1016 0 200 1024 1 200 1032 2 100 1040 1048 type PixelCounter.class 1056 blueCount 0 1064 redCount 2

Slide 70

Slide 70 text

void count(int[] pixels) {
 for (int i = 0; i < pixels.length; i++) {
 int pixel = pixels[i];
 if (pixel == BLUE) blueCount++;
 else if (pixel == RED) redCount++;
 }x }y CPU RAM register name value 0 BLUE 100 1 RED 200 2 this 1048 3 pixels 1000 4 i 2 5 pixels.length 3 6 pixel 200 7 redCount 2 8 offset name value 1000 type int[].class 1008 length 3 1016 0 200 1024 1 200 1032 2 100 1040 1048 type PixelCounter.class 1056 blueCount 0 1064 redCount 2

Slide 71

Slide 71 text

void count(int[] pixels) {
 for (int i = 0; i < pixels.length; i++) {
 int pixel = pixels[i];
 if (pixel == BLUE) blueCount++;
 else if (pixel == RED) redCount++;
 }x }y CPU RAM register name value 0 BLUE 100 1 RED 200 2 this 1048 3 pixels 1000 4 i 2 5 pixels.length 6 pixel 200 7 redCount 2 8 offset name value 1000 type int[].class 1008 length 3 1016 0 200 1024 1 200 1032 2 100 1040 1048 type PixelCounter.class 1056 blueCount 0 1064 redCount 2 3 3

Slide 72

Slide 72 text

void count(int[] pixels) {
 for (int i = 0; i < pixels.length; i++) {
 int pixel = pixels[i];
 if (pixel == BLUE) blueCount++;
 else if (pixel == RED) redCount++;
 }x }y CPU RAM register name value 0 BLUE 100 1 RED 200 2 this 1048 3 pixels 1000 4 i 2 5 pixels.length 3 6 pixel 200 7 redCount 2 8 offset name value 1000 type int[].class 1008 length 3 1016 0 200 1024 1 200 1032 2 100 1040 1048 type PixelCounter.class 1056 blueCount 0 1064 redCount 2

Slide 73

Slide 73 text

void count(int[] pixels) {
 for (int i = 0; i < pixels.length; i++) {
 int pixel = pixels[i];
 if (pixel == BLUE) blueCount++;
 else if (pixel == RED) redCount++;
 }x }y CPU RAM register name value 0 BLUE 100 1 RED 200 2 this 1048 3 pixels 1000 4 i 2 5 pixels.length 3 6 pixel 200 7 redCount 2 8 offset name value 1000 type int[].class 1008 length 3 1016 0 200 1024 1 200 1032 2 100 1040 1048 type PixelCounter.class 1056 blueCount 0 1064 redCount 2 <

Slide 74

Slide 74 text

void count(int[] pixels) {
 for (int i = 0; i < pixels.length; i++) {
 int pixel = pixels[i];
 if (pixel == BLUE) blueCount++;
 else if (pixel == RED) redCount++;
 }x }y CPU RAM register name value 0 BLUE 100 1 RED 200 2 this 1048 3 pixels 1000 4 i 2 5 pixels.length 3 6 pixel 200 7 redCount 2 8 offset name value 1000 type int[].class 1008 length 3 1016 0 200 1024 1 200 1032 2 100 1040 1048 type PixelCounter.class 1056 blueCount 0 1064 redCount 2

Slide 75

Slide 75 text

void count(int[] pixels) {
 for (int i = 0; i < pixels.length; i++) {
 int pixel = pixels[i];
 if (pixel == BLUE) blueCount++;
 else if (pixel == RED) redCount++;
 }x }y CPU RAM register name value 0 BLUE 100 1 RED 200 2 this 1048 3 pixels 1000 4 i 2 5 pixels.length 3 6 pixel 200 7 redCount 2 8 offset name value 1000 type int[].class 1008 length 3 1016 0 200 1024 1 200 1032 2 100 1040 1048 type PixelCounter.class 1056 blueCount 0 1064 redCount 2

Slide 76

Slide 76 text

void count(int[] pixels) {
 for (int i = 0; i < pixels.length; i++) {
 int pixel = pixels[i];
 if (pixel == BLUE) blueCount++;
 else if (pixel == RED) redCount++;
 }x }y CPU RAM register name value 0 BLUE 100 1 RED 200 2 this 1048 3 pixels 1000 4 i 2 5 pixels.length 3 6 pixel 7 redCount 2 8 offset name value 1000 type int[].class 1008 length 3 1016 0 200 1024 1 200 1032 2 100 1040 1048 type PixelCounter.class 1056 blueCount 0 1064 redCount 2 100 200

Slide 77

Slide 77 text

void count(int[] pixels) {
 for (int i = 0; i < pixels.length; i++) {
 int pixel = pixels[i];
 if (pixel == BLUE) blueCount++;
 else if (pixel == RED) redCount++;
 }x }y CPU RAM register name value 0 BLUE 100 1 RED 200 2 this 1048 3 pixels 1000 4 i 2 5 pixels.length 3 6 pixel 100 7 redCount 2 8 offset name value 1000 type int[].class 1008 length 3 1016 0 200 1024 1 200 1032 2 100 1040 1048 type PixelCounter.class 1056 blueCount 0 1064 redCount 2

Slide 78

Slide 78 text

void count(int[] pixels) {
 for (int i = 0; i < pixels.length; i++) {
 int pixel = pixels[i];
 if (pixel == BLUE) blueCount++;
 else if (pixel == RED) redCount++;
 }x }y CPU RAM register name value 0 BLUE 100 1 RED 200 2 this 1048 3 pixels 1000 4 i 2 5 pixels.length 3 6 pixel 100 7 redCount 2 8 offset name value 1000 type int[].class 1008 length 3 1016 0 200 1024 1 200 1032 2 100 1040 1048 type PixelCounter.class 1056 blueCount 0 1064 redCount 2

Slide 79

Slide 79 text

void count(int[] pixels) {
 for (int i = 0; i < pixels.length; i++) {
 int pixel = pixels[i];
 if (pixel == BLUE) blueCount++;
 else if (pixel == RED) redCount++;
 }x }y CPU RAM register name value 0 BLUE 100 1 RED 200 2 this 1048 3 pixels 1000 4 i 2 5 pixels.length 3 6 pixel 100 7 redCount 2 8 offset name value 1000 type int[].class 1008 length 3 1016 0 200 1024 1 200 1032 2 100 1040 1048 type PixelCounter.class 1056 blueCount 0 1064 redCount 2 ==

Slide 80

Slide 80 text

void count(int[] pixels) {
 for (int i = 0; i < pixels.length; i++) {
 int pixel = pixels[i];
 if (pixel == BLUE) blueCount++;
 else if (pixel == RED) redCount++;
 }x }y CPU RAM register name value 0 BLUE 100 1 RED 200 2 this 1048 3 pixels 1000 4 i 2 5 pixels.length 3 6 pixel 100 7 redCount 2 8 offset name value 1000 type int[].class 1008 length 3 1016 0 200 1024 1 200 1032 2 100 1040 1048 type PixelCounter.class 1056 blueCount 0 1064 redCount 2

Slide 81

Slide 81 text

void count(int[] pixels) {
 for (int i = 0; i < pixels.length; i++) {
 int pixel = pixels[i];
 if (pixel == BLUE) blueCount++;
 else if (pixel == RED) redCount++;
 }x }y CPU RAM register name value 0 BLUE 100 1 RED 200 2 this 1048 3 pixels 1000 4 i 2 5 pixels.length 3 6 pixel 100 7 redCount 2 8 offset name value 1000 type int[].class 1008 length 3 1016 0 200 1024 1 200 1032 2 100 1040 1048 type PixelCounter.class 1056 blueCount 0 1064 redCount 2

Slide 82

Slide 82 text

void count(int[] pixels) {
 for (int i = 0; i < pixels.length; i++) {
 int pixel = pixels[i];
 if (pixel == BLUE) blueCount++;
 else if (pixel == RED) redCount++;
 }x }y CPU RAM register name value 0 BLUE 100 1 RED 200 2 this 1048 3 pixels 1000 4 i 2 5 pixels.length 3 6 pixel 100 7 redCount 2 8 offset name value 1000 type int[].class 1008 length 3 1016 0 200 1024 1 200 1032 2 100 1040 1048 type PixelCounter.class 1056 blueCount 0 1064 redCount 2 0 blueCount

Slide 83

Slide 83 text

void count(int[] pixels) {
 for (int i = 0; i < pixels.length; i++) {
 int pixel = pixels[i];
 if (pixel == BLUE) blueCount++;
 else if (pixel == RED) redCount++;
 }x }y CPU RAM register name value 0 BLUE 100 1 RED 200 2 this 1048 3 pixels 1000 4 i 2 5 pixels.length 3 6 pixel 100 7 redCount 2 8 blueCount 0 offset name value 1000 type int[].class 1008 length 3 1016 0 200 1024 1 200 1032 2 100 1040 1048 type PixelCounter.class 1056 blueCount 0 1064 redCount 2

Slide 84

Slide 84 text

void count(int[] pixels) {
 for (int i = 0; i < pixels.length; i++) {
 int pixel = pixels[i];
 if (pixel == BLUE) blueCount++;
 else if (pixel == RED) redCount++;
 }x }y CPU RAM register name value 0 BLUE 100 1 RED 200 2 this 1048 3 pixels 1000 4 i 2 5 pixels.length 3 6 pixel 100 7 redCount 2 8 blueCount 1 offset name value 1000 type int[].class 1008 length 3 1016 0 200 1024 1 200 1032 2 100 1040 1048 type PixelCounter.class 1056 blueCount 0 1064 redCount 2 ++

Slide 85

Slide 85 text

void count(int[] pixels) {
 for (int i = 0; i < pixels.length; i++) {
 int pixel = pixels[i];
 if (pixel == BLUE) blueCount++;
 else if (pixel == RED) redCount++;
 }x }y CPU RAM register name value 0 BLUE 100 1 RED 200 2 this 1048 3 pixels 1000 4 i 2 5 pixels.length 3 6 pixel 100 7 redCount 2 8 blueCount 1 offset name value 1000 type int[].class 1008 length 3 1016 0 200 1024 1 200 1032 2 100 1040 1048 type PixelCounter.class 1056 blueCount 0 1064 redCount 2

Slide 86

Slide 86 text

void count(int[] pixels) {
 for (int i = 0; i < pixels.length; i++) {
 int pixel = pixels[i];
 if (pixel == BLUE) blueCount++;
 else if (pixel == RED) redCount++;
 }x }y CPU RAM register name value 0 BLUE 100 1 RED 200 2 this 1048 3 pixels 1000 4 i 2 5 pixels.length 3 6 pixel 100 7 redCount 2 8 blueCount 1 offset name value 1000 type int[].class 1008 length 3 1016 0 200 1024 1 200 1032 2 100 1040 1048 type PixelCounter.class 1056 blueCount 1064 redCount 2 1 0

Slide 87

Slide 87 text

void count(int[] pixels) {
 for (int i = 0; i < pixels.length; i++) {
 int pixel = pixels[i];
 if (pixel == BLUE) blueCount++;
 else if (pixel == RED) redCount++;
 }x }y CPU RAM register name value 0 BLUE 100 1 RED 200 2 this 1048 3 pixels 1000 4 i 2 5 pixels.length 3 6 pixel 100 7 redCount 2 8 blueCount 1 offset name value 1000 type int[].class 1008 length 3 1016 0 200 1024 1 200 1032 2 100 1040 1048 type PixelCounter.class 1056 blueCount 1 1064 redCount 2

Slide 88

Slide 88 text

void count(int[] pixels) {
 for (int i = 0; i < pixels.length; i++) {
 int pixel = pixels[i];
 if (pixel == BLUE) blueCount++;
 else if (pixel == RED) redCount++;
 }x }y CPU RAM register name value 0 BLUE 100 1 RED 200 2 this 1048 3 pixels 1000 4 i 2 5 pixels.length 3 6 pixel 100 7 redCount 2 8 blueCount 1 offset name value 1000 type int[].class 1008 length 3 1016 0 200 1024 1 200 1032 2 100 1040 1048 type PixelCounter.class 1056 blueCount 1 1064 redCount 2

Slide 89

Slide 89 text

void count(int[] pixels) {
 for (int i = 0; i < pixels.length; i++) {
 int pixel = pixels[i];
 if (pixel == BLUE) blueCount++;
 else if (pixel == RED) redCount++;
 }x }y CPU RAM register name value 0 BLUE 100 1 RED 200 2 this 1048 3 pixels 1000 4 i 3 5 pixels.length 3 6 pixel 100 7 redCount 2 8 blueCount 1 offset name value 1000 type int[].class 1008 length 3 1016 0 200 1024 1 200 1032 2 100 1040 1048 type PixelCounter.class 1056 blueCount 1 1064 redCount 2 ++

Slide 90

Slide 90 text

void count(int[] pixels) {
 for (int i = 0; i < pixels.length; i++) {
 int pixel = pixels[i];
 if (pixel == BLUE) blueCount++;
 else if (pixel == RED) redCount++;
 }x }y CPU RAM register name value 0 BLUE 100 1 RED 200 2 this 1048 3 pixels 1000 4 i 3 5 pixels.length 3 6 pixel 100 7 redCount 2 8 blueCount 1 offset name value 1000 type int[].class 1008 length 3 1016 0 200 1024 1 200 1032 2 100 1040 1048 type PixelCounter.class 1056 blueCount 1 1064 redCount 2

Slide 91

Slide 91 text

void count(int[] pixels) {
 for (int i = 0; i < pixels.length; i++) {
 int pixel = pixels[i];
 if (pixel == BLUE) blueCount++;
 else if (pixel == RED) redCount++;
 }x }y CPU RAM register name value 0 BLUE 100 1 RED 200 2 this 1048 3 pixels 1000 4 i 3 5 pixels.length 3 6 pixel 100 7 redCount 2 8 blueCount 1 offset name value 1000 type int[].class 1008 length 3 1016 0 200 1024 1 200 1032 2 100 1040 1048 type PixelCounter.class 1056 blueCount 1 1064 redCount 2

Slide 92

Slide 92 text

void count(int[] pixels) {
 for (int i = 0; i < pixels.length; i++) {
 int pixel = pixels[i];
 if (pixel == BLUE) blueCount++;
 else if (pixel == RED) redCount++;
 }x }y CPU RAM register name value 0 BLUE 100 1 RED 200 2 this 1048 3 pixels 1000 4 i 3 5 pixels.length 6 pixel 100 7 redCount 2 8 blueCount 1 offset name value 1000 type int[].class 1008 length 3 1016 0 200 1024 1 200 1032 2 100 1040 1048 type PixelCounter.class 1056 blueCount 1 1064 redCount 2 3 3

Slide 93

Slide 93 text

void count(int[] pixels) {
 for (int i = 0; i < pixels.length; i++) {
 int pixel = pixels[i];
 if (pixel == BLUE) blueCount++;
 else if (pixel == RED) redCount++;
 }x }y CPU RAM register name value 0 BLUE 100 1 RED 200 2 this 1048 3 pixels 1000 4 i 3 5 pixels.length 3 6 pixel 100 7 redCount 2 8 blueCount 1 offset name value 1000 type int[].class 1008 length 3 1016 0 200 1024 1 200 1032 2 100 1040 1048 type PixelCounter.class 1056 blueCount 1 1064 redCount 2

Slide 94

Slide 94 text

void count(int[] pixels) {
 for (int i = 0; i < pixels.length; i++) {
 int pixel = pixels[i];
 if (pixel == BLUE) blueCount++;
 else if (pixel == RED) redCount++;
 }x }y CPU RAM register name value 0 BLUE 100 1 RED 200 2 this 1048 3 pixels 1000 4 i 3 5 pixels.length 3 6 pixel 100 7 redCount 2 8 blueCount 1 offset name value 1000 type int[].class 1008 length 3 1016 0 200 1024 1 200 1032 2 100 1040 1048 type PixelCounter.class 1056 blueCount 1 1064 redCount 2 <

Slide 95

Slide 95 text

void count(int[] pixels) {
 for (int i = 0; i < pixels.length; i++) {
 int pixel = pixels[i];
 if (pixel == BLUE) blueCount++;
 else if (pixel == RED) redCount++;
 }x }y CPU RAM register name value 0 BLUE 100 1 RED 200 2 this 1048 3 pixels 1000 4 i 3 5 pixels.length 3 6 pixel 100 7 redCount 2 8 blueCount 1 offset name value 1000 type int[].class 1008 length 3 1016 0 200 1024 1 200 1032 2 100 1040 1048 type PixelCounter.class 1056 blueCount 1 1064 redCount 2

Slide 96

Slide 96 text

Inefficient Memory Access • Unnecessary: fetching values that we already have • Repetitive: fetching one value at a time • Lazy: not fetching until we need the value urgently • Redundant: writing values that we’ll re-write later

Slide 97

Slide 97 text

void count(int[] pixels) {
 for (int i = 0; i < pixels.length; i++) {
 int pixel = pixels[i];
 if (pixel == BLUE) blueCount++; else if (pixel == RED) redCount++;
 }
 } void count(int[] pixels) { 
 int lengthR = pixels.length;
 int blueCountR = blueCount;
 int redCountR = redCount;
 for (int i = 0; i < lengthR; i++) {
 int pixel = pixels[i];
 if (pixel == BLUE) blueCountR++;
 else if (pixel == RED) redCountR++;
 }
 blueCount = blueCountR;
 redCount = redCountR;
 } Reordering Memory Accesses

Slide 98

Slide 98 text

CPU
 CORE 248 RAM 4,294,967,296

Slide 99

Slide 99 text

CPU
 CORE 248 RAM 4,294,967,296 L1 65,536

Slide 100

Slide 100 text

CPU
 CORE 248 RAM 4,294,967,296 L1 65,536 L2 1,572,865

Slide 101

Slide 101 text

CPU
 CORE RAM L1 L2 CPU
 CORE L1 CPU
 CORE L1 CPU
 CORE L1

Slide 102

Slide 102 text

Cheating on Memory Access • Only fetch each value once • Fetch adjacent values together • Anticipate reads and load eagerly • Defer writes

Slide 103

Slide 103 text

}a int blueCount(int[] pixels) {
 int result = 0;
 for (int i = 0; i < pixels.length; i++) {
 if (pixels[i] == BLUE) result++;
 }g
 return result;
 }b int[] newBlueRedMix(int size) {
 int[] result = new int[size];
 for (int i = 0; i < result.length; ) {
 result[i++] = BLUE;
 result[i++] = RED;
 }d
 return result;
 }c boolean initialized;
 int[] pixels;
 
 int initializeAndCount(int size) {
 if (!initialized) {
 pixels = newBlueRedMix(size);
 initialized = true;
 }f
 return blueCount(pixels);
 }e public class PixelCounter {
 public static final int BLUE = 100;
 public static final int RED = 200;

Slide 104

Slide 104 text

}a int blueCount(int[] pixels) {
 int result = 0;
 for (int i = 0; i < pixels.length; i++) {
 if (pixels[i] == BLUE) result++;
 }g
 return result;
 }b int[] newBlueRedMix(int size) {
 int[] result = new int[size];
 for (int i = 0; i < result.length; ) {
 result[i++] = BLUE;
 result[i++] = RED;
 }d
 return result;
 }c boolean initialized;
 int[] pixels;
 
 int initializeAndCount(int size) {
 if (!initialized) {
 pixels = newBlueRedMix(size);
 initialized = true;
 }f
 return blueCount(pixels);
 }e public class PixelCounter {
 public static final int BLUE = 100;
 public static final int RED = 200;

Slide 105

Slide 105 text

}a int[] newBlueRedMix(int size) {
 int[] result = new int[size];
 for (int i = 0; i < result.length; ) {
 result[i++] = BLUE;
 result[i++] = RED;
 }d
 return result;
 }c boolean initialized;
 int[] pixels;
 
 int initializeAndCount(int size) {
 if (!initialized) {
 pixels = newBlueRedMix(size);
 initialized = true;
 }f
 return blueCount(pixels);
 }e public class PixelCounter {
 public static final int BLUE = 100;
 public static final int RED = 200; int blueCount(int[] pixels) {
 int result = 0;
 for (int i = 0; i < pixels.length; i++) {
 if (pixels[i] == BLUE) result++;
 }g
 return result;
 }b

Slide 106

Slide 106 text

}a int blueCount(int[] pixels) {
 int result = 0;
 for (int i = 0; i < pixels.length; i++) {
 if (pixels[i] == BLUE) result++;
 }g
 return result;
 }b int[] newBlueRedMix(int size) {
 int[] result = new int[size];
 for (int i = 0; i < result.length; ) {
 result[i++] = BLUE;
 result[i++] = RED;
 }d
 return result;
 }c boolean initialized;
 int[] pixels;
 
 int initializeAndCount(int size) {
 if (!initialized) {
 pixels = newBlueRedMix(size);
 initialized = true;
 }f
 return blueCount(pixels);
 }e public class PixelCounter {
 public static final int BLUE = 100;
 public static final int RED = 200;

Slide 107

Slide 107 text

}a int blueCount(int[] pixels) {
 int result = 0;
 for (int i = 0; i < pixels.length; i++) {
 if (pixels[i] == BLUE) result++;
 }g
 return result;
 }b boolean initialized;
 int[] pixels;
 
 int initializeAndCount(int size) {
 if (!initialized) {
 pixels = newBlueRedMix(size);
 initialized = true;
 }f
 return blueCount(pixels);
 }e public class PixelCounter {
 public static final int BLUE = 100;
 public static final int RED = 200; int[] newBlueRedMix(int size) {
 int[] result = new int[size];
 for (int i = 0; i < result.length; ) {
 result[i++] = BLUE;
 result[i++] = RED;
 }d
 return result;
 }c

Slide 108

Slide 108 text

}a int blueCount(int[] pixels) {
 int result = 0;
 for (int i = 0; i < pixels.length; i++) {
 if (pixels[i] == BLUE) result++;
 }g
 return result;
 }b int[] newBlueRedMix(int size) {
 int[] result = new int[size];
 for (int i = 0; i < result.length; ) {
 result[i++] = BLUE;
 result[i++] = RED;
 }d
 return result;
 }c boolean initialized;
 int[] pixels;
 
 int initializeAndCount(int size) {
 if (!initialized) {
 pixels = newBlueRedMix(size);
 initialized = true;
 }f
 return blueCount(pixels);
 }e public class PixelCounter {
 public static final int BLUE = 100;
 public static final int RED = 200;

Slide 109

Slide 109 text

}a int blueCount(int[] pixels) {
 int result = 0;
 for (int i = 0; i < pixels.length; i++) {
 if (pixels[i] == BLUE) result++;
 }g
 return result;
 }b int[] newBlueRedMix(int size) {
 int[] result = new int[size];
 for (int i = 0; i < result.length; ) {
 result[i++] = BLUE;
 result[i++] = RED;
 }d
 return result;
 }c public class PixelCounter {
 public static final int BLUE = 100;
 public static final int RED = 200; boolean initialized;
 int[] pixels;
 
 int initializeAndCount(int size) {
 if (!initialized) {
 pixels = newBlueRedMix(size);
 initialized = true;
 }f
 return blueCount(pixels);
 }e

Slide 110

Slide 110 text

}a int blueCount(int[] pixels) {
 int result = 0;
 for (int i = 0; i < pixels.length; i++) {
 if (pixels[i] == BLUE) result++;
 }g
 return result;
 }b int[] newBlueRedMix(int size) {
 int[] result = new int[size];
 for (int i = 0; i < result.length; ) {
 result[i++] = BLUE;
 result[i++] = RED;
 }d
 return result;
 }c boolean initialized;
 int[] pixels;
 
 int initializeAndCount(int size) {
 if (!initialized) {
 pixels = newBlueRedMix(size);
 initialized = true;
 }f
 return blueCount(pixels);
 }e public class PixelCounter {
 public static final int BLUE = 100;
 public static final int RED = 200;

Slide 111

Slide 111 text

}a int blueCount(int[] pixels) {
 int result = 0;
 for (int i = 0; i < pixels.length; i++) {
 if (pixels[i] == BLUE) result++;
 }g
 return result;
 }b int[] newBlueRedMix(int size) {
 int[] result = new int[size];
 for (int i = 0; i < result.length; ) {
 result[i++] = BLUE;
 result[i++] = RED;
 }d
 return result;
 }c boolean initialized;
 int[] pixels;
 
 int initializeAndCount(int size) {
 if (!initialized) {
 pixels = newBlueRedMix(size);
 initialized = true;
 }f
 return blueCount(pixels);
 }e public class PixelCounter {
 public static final int BLUE = 100;
 public static final int RED = 200;

Slide 112

Slide 112 text

}a int blueCount(int[] pixels) {
 int result = 0;
 for (int i = 0; i < pixels.length; i++) {
 if (pixels[i] == BLUE) result++;
 }g
 return result;
 }b int[] newBlueRedMix(int size) {
 int[] result = new int[size];
 for (int i = 0; i < result.length; ) {
 result[i++] = BLUE;
 result[i++] = RED;
 }d
 return result;
 }c boolean initialized;
 int[] pixels;
 
 int initializeAndCount(int size) {
 if (!initialized) {
 pixels = newBlueRedMix(size);
 initialized = true;
 }f
 return blueCount(pixels);
 }e public class PixelCounter {
 public static final int BLUE = 100;
 public static final int RED = 200; Is this safe? • We guard access to the pixels with initialized • What if multiple threads call initializeAndCount?

Slide 113

Slide 113 text

}a int blueCount(int[] pixels) {
 int result = 0;
 for (int i = 0; i < pixels.length; i++) {
 if (pixels[i] == BLUE) result++;
 }g
 return result;
 }b int[] newBlueRedMix(int size) {
 int[] result = new int[size];
 for (int i = 0; i < result.length; ) {
 result[i++] = BLUE;
 result[i++] = RED;
 }d
 return result;
 }c boolean initialized;
 int[] pixels;
 
 int initializeAndCount(int size) {
 if (!initialized) {
 pixels = newBlueRedMix(size);
 initialized = true;
 }f
 return blueCount(pixels);
 }e public class PixelCounter {
 public static final int BLUE = 100;
 public static final int RED = 200; Unsafe! • One thread reorders the writes, writing initialized before pixels • Another thread reads the new value of initialized but the old value of pixels NullPointerException

Slide 114

Slide 114 text

Surprise! • Reordered code and memory access make impossible things possible

Slide 115

Slide 115 text

https://github.com/googlesamples/android-architecture

Slide 116

Slide 116 text

// Invoked on the loader thread
 void processLoadedTasks(List tasks) {
 ... 
 for (Task task : tasks) {
 mCachedTasks.put(task.getId(), task);
 }
 ... }
 
 // Invoked on the Main thread
 void saveTask(Task task) {
 ...
 
 mCachedTasks.put(task.getId(), task);
 
 ... } • The Repository has a LinkedHashMap of todo items • The loader thread inserts task objects downloaded from the server • The UI inserts task objects entered by the user Is this safe?

Slide 117

Slide 117 text

• When multiple threads access the same object at the same time, bad things happen • The object could be corrupted, it could lose data, or it could crash Unsafe! // Invoked on the loader thread
 void processLoadedTasks(List tasks) {
 ... 
 for (Task task : tasks) {
 mCachedTasks.put(task.getId(), task);
 }
 ... }
 
 // Invoked on the Main thread
 void saveTask(Task task) {
 ...
 
 mCachedTasks.put(task.getId(), task);
 
 ... } ArrayIndexOutOfBoundsException

Slide 118

Slide 118 text

Fragile • Code that are correct in isolation may be broken when run concurrently • Tests don’t provide much confidence • One-in-a-million bugs happen all of the time

Slide 119

Slide 119 text

An Inventory of Weapons PART 2

Slide 120

Slide 120 text

• Make a Runnable, create a Thread, and you’re done • Don’t forget to set a name! ExecutorService • Creating hundreds of threads is expensive • ExecutorService manages a list of threads, and accepts work to run on ’em • Don’t forget to set a name with ThreadFactory Thread VS

Slide 121

Slide 121 text

boolean initialized; int[] pixels;
 
 int initializeAndCount(int size) {
 if (!initialized) {
 pixels = newBlueRedMix(size);
 initialized = true;
 }f
 return blueCount(pixels);
 }e Volatile Fields volatile • Always read a fresh value from memory • Always write to memory immediately

Slide 122

Slide 122 text

• When you read a volatile field, all reads are refreshed • When you write a volatile field, all writes are flushed Volatile Isn’t Local

Slide 123

Slide 123 text

• blueCount++ does a read and a write • Another thread might write blueCount between the read and write Volatile Isn’t Atomic

Slide 124

Slide 124 text

int initializeAndCount(int size) { Synchronized Methods boolean initialized;
 int[] pixels;
 
 
 if (!initialized) {
 pixels = newBlueRedMix(size);
 initialized = true;
 }
 return blueCount(pixels);
 } synchronized

Slide 125

Slide 125 text

• Every object has a lock • Calling a synchronized method: • Acquire the lock, waiting for other threads if necessary • Run the code • Release the lock How Synchronized Works

Slide 126

Slide 126 text

• When entering a synchronized block, all reads are refreshed • When exiting a synchronized block, all writes are flushed Synchronized & Memory

Slide 127

Slide 127 text

Synchronized is Blocking 0 1 2 3 4 5 6 7 8 9 10 blueCount blueCount 0 blueCount 0

Slide 128

Slide 128 text

Synchronized is Blocking 0 1 2 3 4 5 6 7 blueCount blueCount 13 blueCount 0

Slide 129

Slide 129 text

Synchronized is Blocking 0 1 2 3 blueCount blueCount 13 blueCount 13

Slide 130

Slide 130 text

• Lock granularity: how many locks you have • Too many: correctness problems, risk of deadlock • Too few: jank, blocked threads • OkHttp has a 4-page design document describing its internal use of synchronized Synchronized is Difficult! https://github.com/square/okhttp/wiki/Concurrency

Slide 131

Slide 131 text

• AtomicInteger, AtomicReference, etc. • Non-blocking like volatile, atomic like synchronized Atomics

Slide 132

Slide 132 text

• 3, 2, 1, blast off! CountDownLatch

Slide 133

Slide 133 text

• Like HashMap, but for use by many threads • May be overkill for single-user applications ConcurrentHashMap

Slide 134

Slide 134 text

• Makes producer-consumer problems easy • Blocking put() for easy backpressure • Be careful about capacity BlockingQueue

Slide 135

Slide 135 text

ScheduledThreadPoolExecutor • Run code after a delay, or on a repeating interval • Handler.postDelayed() is often much better because you want to be on main thread

Slide 136

Slide 136 text

CONCURRENCY IN PRACTICE JAVA BRIAN GOETZ AND FIVE OTHER GENIUSES

Slide 137

Slide 137 text

Effective Concurrency PART 3

Slide 138

Slide 138 text

Main Thread is the Boss • It owns all data • It assigns immutable tasks to worker threads • Workers post immutable results back to the main thread

Slide 139

Slide 139 text

Immutable Values • Once an object is shared between threads, changing that object is unsafe • Objects that never change are always safe!

Slide 140

Slide 140 text

Implementing Immutable • All fields are final, and immutable • You’ll need builders • Be careful about collections • AutoValue • Kotlin data classes Effective Java JOSH BLOCH Version 2

Slide 141

Slide 141 text

Models go on the Main Thread • Mutable application state goes on the main thread • Keep your main thread synchronous • Avoid using Handler.post() from the main thread

Slide 142

Slide 142 text

No content

Slide 143

Slide 143 text

I/O goes on Worker Threads • Be deliberate about posting back to the main thread • Listeners • Libraries • @MainThread, @WorkerThread

Slide 144

Slide 144 text

final BehaviorSubject> restaurantsSubject = BehaviorSubject.create();
 public void onUpdate(List restaurants) {
 checkMainThread();
 restaurantsSubject.onNext(restaurants);
 }
 void checkMainThread() {
 if (Looper.myLooper() != Looper.getMainLooper()) {
 throw new AssertionError("Must be on main thread");
 }
 } Rx on Main

Slide 145

Slide 145 text

No content

Slide 146

Slide 146 text

Recap • Concurrency is difficult • There’s a bunch of language features and APIs • Access models on the main thread

Slide 147

Slide 147 text

@jessewilson https://github.com/swankjesse/concurrency Thanks