Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Coordinating Space and Time (Chicago Roboto 2017)

Coordinating Space and Time (Chicago Roboto 2017)

Video: https://www.youtube.com/watch?v=yS0Nc-L1Uuk
Code: https://github.com/swankjesse/concurrency

One of Android’s core requirements is that the UI runs on the main thread and IO in the background. Though concurrency is powerful, it’s also frustrating to deal with forking threads.

In this talk we’ll:

⏰ Learn how smartphone CPUs contradict your memory
⏰ Discuss how Android’s compilers disregard your orders
⏰ Sync up on Java’s concurrency APIs
⏰ See how to make sexy apps that aren’t racy
⏰ Determine if reactive programming is the future

This talk covers a sequence of concurrency topics. Attendees will be able to fix volatile programs and block threading bugs before they happen.

Jesse Wilson

April 20, 2017
Tweet

More Decks by Jesse Wilson

Other Decks in Technology

Transcript

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

    View full-size slide

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

    View full-size slide

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

    View full-size slide

  4. Why is Concurrency Difficult?
    PART 1

    View full-size slide

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

    View full-size slide

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

    View full-size slide

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

    View full-size slide

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

    View full-size slide

  9. • 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

    View full-size slide

  10. • Random-Access Memory
    • Where your data is
    • When the CPU runs

    new ArrayList()

    an area of memory is assigned
    to hold the corresponding
    object

    View full-size slide

  11. 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
    . . .

    View full-size slide

  12. 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
    . . .

    View full-size slide

  13. Example: Pixel Counter
    blueCount 1
    redCount 2

    View full-size slide

  14. 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++;

    }

    }
    }

    View full-size slide

  15. 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

    View full-size slide

  16. 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

    View full-size slide

  17. 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

    View full-size slide

  18. 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

    View full-size slide

  19. 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

    View full-size slide

  20. 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

    View full-size slide

  21. 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

    View full-size slide

  22. 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

    View full-size slide

  23. 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

    View full-size slide

  24. 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
    <

    View full-size slide

  25. 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

    View full-size slide

  26. 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

    View full-size slide

  27. 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

    View full-size slide

  28. 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

    View full-size slide

  29. 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

    View full-size slide

  30. 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
    ==

    View full-size slide

  31. 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

    View full-size slide

  32. 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

    View full-size slide

  33. 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
    ==

    View full-size slide

  34. 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

    View full-size slide

  35. 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

    View full-size slide

  36. 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

    View full-size slide

  37. 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

    View full-size slide

  38. 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
    ++

    View full-size slide

  39. 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

    View full-size slide

  40. 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

    View full-size slide

  41. 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

    View full-size slide

  42. 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

    View full-size slide

  43. 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
    ++

    View full-size slide

  44. 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

    View full-size slide

  45. 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

    View full-size slide

  46. 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

    View full-size slide

  47. 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

    View full-size slide

  48. 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
    <

    View full-size slide

  49. 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

    View full-size slide

  50. 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

    View full-size slide

  51. 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

    View full-size slide

  52. 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

    View full-size slide

  53. 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

    View full-size slide

  54. 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
    ==

    View full-size slide

  55. 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

    View full-size slide

  56. 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

    View full-size slide

  57. 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
    ==

    View full-size slide

  58. 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

    View full-size slide

  59. 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

    View full-size slide

  60. 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

    View full-size slide

  61. 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

    View full-size slide

  62. 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
    ++

    View full-size slide

  63. 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

    View full-size slide

  64. 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

    View full-size slide

  65. 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

    View full-size slide

  66. 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

    View full-size slide

  67. 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
    ++

    View full-size slide

  68. 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

    View full-size slide

  69. 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

    View full-size slide

  70. 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

    View full-size slide

  71. 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

    View full-size slide

  72. 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
    <

    View full-size slide

  73. 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

    View full-size slide

  74. 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

    View full-size slide

  75. 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

    View full-size slide

  76. 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

    View full-size slide

  77. 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

    View full-size slide

  78. 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
    ==

    View full-size slide

  79. 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

    View full-size slide

  80. 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

    View full-size slide

  81. 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

    View full-size slide

  82. 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

    View full-size slide

  83. 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
    ++

    View full-size slide

  84. 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

    View full-size slide

  85. 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

    View full-size slide

  86. 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

    View full-size slide

  87. 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

    View full-size slide

  88. 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
    ++

    View full-size slide

  89. 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

    View full-size slide

  90. 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

    View full-size slide

  91. 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

    View full-size slide

  92. 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

    View full-size slide

  93. 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
    <

    View full-size slide

  94. 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

    View full-size slide

  95. 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

    View full-size slide

  96. 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

    View full-size slide

  97. CPU

    CORE
    248
    RAM
    4,294,967,296

    View full-size slide

  98. CPU

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

    View full-size slide

  99. CPU

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

    View full-size slide

  100. CPU

    CORE
    RAM
    L1
    L2
    CPU

    CORE
    L1
    CPU

    CORE
    L1
    CPU

    CORE
    L1

    View full-size slide

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

    View full-size slide

  102. }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;

    View full-size slide

  103. }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;

    View full-size slide

  104. }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

    View full-size slide

  105. }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;

    View full-size slide

  106. }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

    View full-size slide

  107. }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;

    View full-size slide

  108. }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

    View full-size slide

  109. }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;

    View full-size slide

  110. }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;

    View full-size slide

  111. }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?

    View full-size slide

  112. }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

    View full-size slide

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

    View full-size slide

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

    View full-size slide

  115. // 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?

    View full-size slide

  116. • 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

    View full-size slide

  117. 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

    View full-size slide

  118. An Inventory of Weapons
    PART 2

    View full-size slide

  119. • 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

    View full-size slide

  120. 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

    View full-size slide

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

    View full-size slide

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

    View full-size slide

  123. int initializeAndCount(int size) {
    Synchronized Methods
    boolean initialized;

    int[] pixels;



    if (!initialized) {

    pixels = newBlueRedMix(size);

    initialized = true;

    }

    return blueCount(pixels);

    }
    synchronized

    View full-size slide

  124. • 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

    View full-size slide

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

    View full-size slide

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

    View full-size slide

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

    View full-size slide

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

    View full-size slide

  129. • 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

    View full-size slide

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

    View full-size slide

  131. • 3, 2, 1, blast off!
    CountDownLatch

    View full-size slide

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

    View full-size slide

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

    View full-size slide

  134. 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

    View full-size slide

  135. CONCURRENCY
    IN PRACTICE
    JAVA
    BRIAN GOETZ
    AND FIVE OTHER GENIUSES

    View full-size slide

  136. Effective Concurrency
    PART 3

    View full-size slide

  137. 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

    View full-size slide

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

    View full-size slide

  139. 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

    View full-size slide

  140. 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

    View full-size slide

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

    View full-size slide

  142. 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

    View full-size slide

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

    View full-size slide

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

    View full-size slide