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

The Mutable State Monster and How to defeat it

Bb85fb6625cd8721ed9c4784256dc4de?s=47 Anup Cowkur
October 15, 2016

The Mutable State Monster and How to defeat it

Bb85fb6625cd8721ed9c4784256dc4de?s=128

Anup Cowkur

October 15, 2016
Tweet

Transcript

  1. THE MUTABLE STATE MONSTER AND HOW TO DEFEAT IT ANUP

    COWKUR
  2. None
  3. PROLOGUE

  4. WHAT IS STATE?

  5. WHAT IS STATE? WIKIPEDIA A computer program stores data in

    variables, which represent storage locations in the computer's memory. The contents of these memory locations, at any given point in the program's execution, is called the program's state.
  6. STATE IS THE CURRENT VALUE OF DATA AT ANY POINT

    OF EXECUTION OF THE PROGRAM –Me TEXT
  7. CHAPTER 1: THE WIZARD

  8. A LONG TIME AGO, THERE WAS A GRAND WIZARD

  9. JOHN MCCARTHY ACTUAL PHOTO

  10. HE PIONEERED ARTIFICIAL INTELLIGENCE

  11. IN 1958, HE CAME UP WITH A LITTLE LANGUAGE CALLED

    LISP
  12. LISP ACTUAL SYNTAX

  13. LISP WAS THE FIRST LANGUAGE TO HAVE AUTOMATIC MEMORY MANAGEMENT

    USING A GARBAGE COLLECTOR
  14. IT WAS ALSO ONE OF THE FIRST LANGUAGE TO HAVE

    ATOMS - DATA THAT COULD NOT BE DIVIDED FURTHER
  15. BUT WHY?

  16. CHAPTER 2: THE MONSTER

  17. DO THE FOLLOWING PROGRAMS WORK CORRECTLY IN A MULTI- THREADED

    SYSTEM?
  18. PROGRAM 1

  19. public void checkAndPut(final String key,
 final String value) {
 if

    (!map.containsKey(key)) {
 map.put(key, value);
 }
 }
  20. public void checkAndPut(final String key,
 final String value) {
 if

    (!map.containsKey(key)) {
 map.put(key, value);
 }
 }
  21. public void checkAndPut(final String key,
 final String value) {
 if

    (!map.containsKey(key)) {
 map.put(key, value);
 }
 }
  22. public void checkAndPut(final String key,
 final String value) {
 if

    (!map.containsKey(key)) { < - Thread 1
 map.put(key, value);
 }
 }
  23. public void checkAndPut(final String key,
 final String value) {
 if

    (!map.containsKey(key)) {
 map.put(key, value);
 }
 } Thread 2 removes key from map
  24. public void checkAndPut(final String key,
 final String value) {
 if

    (!map.containsKey(key)) {
 map.put(key, value); <- Thread 1
 }
 }
  25. public void checkAndPut(final String key,
 final String value) {
 if

    (!map.containsKey(key)) {
 map.put(key, value);
 }
 }
  26. CHECK-THEN-ACT PROBLEM

  27. WE CAN FIX IT!

  28. public void checkAndPut(final String key,
 final String value) {
 synchronized

    (this) {
 if (!map.containsKey(key)) {
 map.put(key, value);
 }
 }
 }
  29. public void checkAndPut(final String key,
 final String value) {
 synchronized

    (this) {
 if (!map.containsKey(key)) {
 map.put(key, value);
 }
 }
 }
  30. PROGRAM 2

  31. public class EntCounter {
 private long count = 0;
 


    public long increment() {
 return ++count;
 }
 }
  32. public class EntCounter {
 private long count = 0;
 


    public long increment() {
 return ++count;
 }
 }
  33. public class EntCounter {
 private long count = 0;
 


    public long increment() {
 return ++count;
 }
 }
  34. public class EntCounter {
 private long count = 0;
 


    public long increment() {
 return ++count; <- Thread 1
 }
 }
  35. public class EntCounter {
 private long count = 0;
 


    public long increment() {
 1. Read
 return ++count; 2. Modify
 3. Write 
 }
 }
  36. public class EntCounter {
 private long count = 0;
 


    public long increment() {
 1. Read <- Thread 1
 return ++count; 2. Modify
 3. Write 
 }
 }
  37. public class EntCounter {
 private long count = 0;
 


    public long increment() {
 1. Read <- Thread 1
 return ++count; 2. Modify
 3. Write 
 }
 } Thread 2 modifies the value of count
  38. public class EntCounter {
 private long count = 0;
 


    public long increment() {
 1. Read
 return ++count; 2. Modify <- Thread 1
 3. Write 
 }
 }
  39. public class EntCounter {
 private long count = 0;
 


    public long increment() {
 1. Read
 return ++count; 2. Modify
 3. Write <- Thread 1 
 }
 }
  40. public class EntCounter {
 private long count = 0;
 


    public long increment() {
 1. Read
 return ++count; 2. Modify
 3. Write
 }
 }
  41. READ-MODIFY- WRITE PROBLEM

  42. BUT WE CAN FIX IT!

  43. public class EntCounter {
 private long count = 0;
 


    public long increment() {
 synchronized (this) {
 return ++count;
 }
 }
 }
  44. public class EntCounter {
 private long count = 0;
 


    public long increment() {
 synchronized (this) {
 return ++count;
 }
 }
 }
  45. PROGRAM 3

  46. public class RunFrodoRun {
 
 private boolean stopped = false;


    
 public void run() {
 while (!stopped) {
 // RUN!!!
 }
 }
 
 public void stop() {
 this.stopped = true;
 }
 }
  47. public class RunFrodoRun {
 
 private boolean stopped = false;


    
 public void run() {
 while (!stopped) {
 // RUN!!!
 }
 }
 
 public void stop() {
 this.stopped = true;
 }
 }
  48. public class RunFrodoRun {
 
 private boolean stopped = false;


    
 public void run() {
 while (!stopped) {
 // RUN!!!
 }
 }
 
 public void stop() {
 this.stopped = true;
 }
 }
  49. public class RunFrodoRun {
 
 private boolean stopped = false;


    
 public void run() {
 while (!stopped) {
 // RUN!!!
 }
 }
 
 public void stop() {
 this.stopped = true;
 }
 }
  50. public class RunFrodoRun {
 
 private boolean stopped = false;


    
 public void run() {
 while (!stopped) {
 // RUN!!!
 }
 }
 
 public void stop() {
 this.stopped = true;
 }
 }
  51. public class RunFrodoRun {
 
 private boolean stopped = false;


    
 public void run() {
 while (!stopped) {
 // RUN!!!
 }
 }
 
 public void stop() {
 this.stopped = true;
 }
 }
  52. public class RunFrodoRun {
 
 private boolean stopped = false;


    
 public void run() { <- Thread 1
 while (!stopped) {
 // RUN!!!
 }
 }
 
 public void stop() {
 this.stopped = true;
 }
 }
  53. public class RunFrodoRun {
 
 private boolean stopped = false;


    
 public void run() {
 while (!stopped) {
 // RUN!!!
 }
 }
 
 public void stop() { <- Thread 2
 this.stopped = true;
 }
 }
  54. public class RunFrodoRun {
 
 private boolean stopped = false;


    
 public void run() {
 while (!stopped) { <- Thread 1
 // RUN!!!
 }
 }
 
 public void stop() {
 this.stopped = true;
 }
 }
  55. public class RunFrodoRun {
 
 private boolean stopped = false;


    
 public void run() {
 while (!stopped) { <- Thread 1
 // RUN!!!
 }
 }
 
 public void stop() {
 this.stopped = true;
 }
 } MAIN MEMORY stopped
  56. public class RunFrodoRun {
 
 private boolean stopped = false;


    
 public void run() {
 while (!stopped) { <- Thread 1
 // RUN!!!
 }
 }
 
 public void stop() {
 this.stopped = true;
 }
 } MAIN MEMORY stopped THREAD LOCAL stopped
  57. public class RunFrodoRun {
 
 private boolean stopped = false;


    
 public void run() {
 while (!stopped) { <- Thread 1
 // RUN!!!
 }
 }
 
 public void stop() {
 this.stopped = true;
 }
 } MAIN MEMORY stopped THREAD LOCAL stopped L1/L2 PROCESSOR CACHE stopped
  58. public class RunFrodoRun {
 
 private boolean stopped = false;


    
 public void run() {
 while (!stopped) {
 // RUN!!!
 }
 }
 
 public void stop() {
 this.stopped = true;
 }
 }
  59. VISIBILITY PROBLEM

  60. WE CAN SOOOO FIX THIS!

  61. public class RunFrodoRun {
 
 private volatile boolean stopped =

    false;
 
 public void run() {
 while (!stopped) {
 // RUN!!!
 }
 }
 
 public void stop() {
 this.stopped = true;
 }
 }
  62. public class RunFrodoRun {
 
 private volatile boolean stopped =

    false;
 
 public void run() {
 while (!stopped) {
 // RUN!!!
 }
 }
 
 public void stop() {
 this.stopped = true;
 }
 }
  63. PROGRAM 4

  64. public class OrcFunerals {
 int orcsKilledYesterday = 0;
 int orcsKilledToday

    = 0;
 
 public void init() {
 orcsKilledYesterday = 1;
 orcsKilledToday = 2;
 }
 
 public int getDeadOrcs() {
 return orcsKilledYesterday + orcsKilledToday;
 }
 }
  65. public class OrcFunerals {
 int orcsKilledYesterday = 0;
 int orcsKilledToday

    = 0;
 
 public void init() {
 orcsKilledYesterday = 1;
 orcsKilledToday = 2;
 }
 
 public int getDeadOrcs() {
 return orcsKilledYesterday + orcsKilledToday;
 }
 }
  66. public class OrcFunerals {
 int orcsKilledYesterday = 0;
 int orcsKilledToday

    = 0;
 
 public void init() {
 orcsKilledYesterday = 1;
 orcsKilledToday = 2;
 }
 
 public int getDeadOrcs() {
 return orcsKilledYesterday + orcsKilledToday;
 }
 }
  67. public class OrcFunerals {
 int orcsKilledYesterday = 0;
 int orcsKilledToday

    = 0;
 
 public void init() {
 orcsKilledYesterday = 1;
 orcsKilledToday = 2;
 }
 
 public int getDeadOrcs() {
 return orcsKilledYesterday + orcsKilledToday;
 }
 }
  68. public class OrcFunerals {
 int orcsKilledYesterday = 0;
 int orcsKilledToday

    = 0;
 
 public void init() {
 orcsKilledYesterday = 1;
 orcsKilledToday = 2;
 }
 
 public int getDeadOrcs() {
 return orcsKilledYesterday + orcsKilledToday;
 }
 }
  69. public class OrcFunerals {
 int orcsKilledYesterday = 0;
 int orcsKilledToday

    = 0;
 
 public void init() {
 orcsKilledYesterday = 1;
 orcsKilledToday = 2;
 }
 
 public int getDeadOrcs() {
 return orcsKilledYesterday + orcsKilledToday;
 }
 }
  70. public class OrcFunerals {
 int orcsKilledYesterday = 0;
 int orcsKilledToday

    = 0;
 
 public void init() {
 orcsKilledYesterday = 1; <- thread 1
 orcsKilledToday = 2;
 }
 
 public int getDeadOrcs() {
 return orcsKilledYesterday + orcsKilledToday;
 }
 }
  71. public class OrcFunerals {
 int orcsKilledYesterday = 0;
 int orcsKilledToday

    = 0;
 
 public void init() {
 orcsKilledYesterday = 1;
 orcsKilledToday = 2;
 }
 
 public int getDeadOrcs() { <- Thread 2
 return orcsKilledYesterday + orcsKilledToday;
 }
 }
  72. public class OrcFunerals {
 int orcsKilledYesterday = 0;
 int orcsKilledToday

    = 0;
 
 public void init() {
 orcsKilledYesterday = 1;
 orcsKilledToday = 2;
 }
 
 public int getDeadOrcs() {
 return orcsKilledYesterday + orcsKilledToday;
 }
 } Result should be 1
  73. public class OrcFunerals {
 int orcsKilledYesterday = 0;
 int orcsKilledToday

    = 0;
 
 public void init() {
 orcsKilledYesterday = 1;
 orcsKilledToday = 2;
 }
 
 public int getDeadOrcs() {
 return orcsKilledYesterday + orcsKilledToday;
 }
 } But the JVM can re-order incorrectly synchronized operations
  74. public class OrcFunerals {
 int orcsKilledYesterday = 0;
 int orcsKilledToday

    = 0;
 
 public void init() {
 orcsKilledYesterday = 1; <- Operation 1
 orcsKilledToday = 2; <- Operation 2
 }
 
 public int getDeadOrcs() {
 return orcsKilledYesterday + orcsKilledToday;
 }
 }
  75. public class OrcFunerals {
 int orcsKilledYesterday = 0;
 int orcsKilledToday

    = 0;
 
 public void init() { orcsKilledToday = 2; <- Operation 2
 orcsKilledYesterday = 1; <- Operation 1
 }
 
 public int getDeadOrcs() {
 return orcsKilledYesterday + orcsKilledToday;
 }
 }
  76. public class OrcFunerals {
 int orcsKilledYesterday = 0;
 int orcsKilledToday

    = 0;
 
 public void init() { orcsKilledToday = 2; <- Thread 1
 orcsKilledYesterday = 1;
 }
 
 public int getDeadOrcs() {
 return orcsKilledYesterday + orcsKilledToday;
 }
 }
  77. public class OrcFunerals {
 int orcsKilledYesterday = 0;
 int orcsKilledToday

    = 0;
 
 public void init() {
 orcsKilledYesterday = 1;
 orcsKilledToday = 2;
 }
 
 public int getDeadOrcs() { <- Thread 2
 return orcsKilledYesterday + orcsKilledToday;
 }
 }
  78. public class OrcFunerals {
 int orcsKilledYesterday = 0;
 int orcsKilledToday

    = 0;
 
 public void init() { orcsKilledToday = 2;
 orcsKilledYesterday = 1;
 }
 
 public int getDeadOrcs() {
 return orcsKilledYesterday + orcsKilledToday;
 }
 } Result in this case will be 2
  79. public class OrcFunerals {
 int orcsKilledYesterday = 0;
 int orcsKilledToday

    = 0;
 
 public void init() { orcsKilledToday = 2;
 orcsKilledYesterday = 1;
 }
 
 public int getDeadOrcs() {
 return orcsKilledYesterday + orcsKilledToday;
 }
 }
  80. ORDERING PROBLEM

  81. FIX!

  82. public class OrcFunerals {
 volatile int orcsKilledYesterday = 0;
 volatile

    int orcsKilledToday = 0;
 
 public void init() {
 orcsKilledYesterday = 1;
 orcsKilledToday = 2;
 }
 
 public int getDeadOrcs() {
 return orcsKilledYesterday + orcsKilledToday;
 }
 }
  83. public class OrcFunerals {
 volatile int orcsKilledYesterday = 0;
 volatile

    int orcsKilledToday = 0;
 
 public void init() {
 orcsKilledYesterday = 1;
 orcsKilledToday = 2;
 }
 
 public int getDeadOrcs() {
 return orcsKilledYesterday + orcsKilledToday;
 }
 }
  84. BUT WE FIXED IT, RIGHT?

  85. USER

  86. USER ORDERS

  87. USER ORDERS PAYMENT

  88. USER ORDERS PAYMENT ACTIVITY 1

  89. USER ORDERS PAYMENT ACTIVITY 1 ACTIVITY 2

  90. USER ORDERS PAYMENT ACTIVITY 1 ACTIVITY 2 SYNCHRONIZE

  91. USER ORDERS PAYMENT ACTIVITY 1 ACTIVITY 2 ACTIVITY 3 SYNCHRONIZE

  92. USER ORDERS PAYMENT ACTIVITY 1 ACTIVITY 2 ACTIVITY 3 SYNCHRONIZE

    CHAT
  93. USER ORDERS PAYMENT ACTIVITY 1 ACTIVITY 2 ACTIVITY 3 CHAT

    ACTIVITY 4 SYNCHRONIZE
  94. None
  95. SYNCHRONIZE

  96. DEADLOCK

  97. SAY SYNCHRONIZE ONE MORE TIME!!!

  98. CONCURRENCY IS HARD

  99. OUR BRAINS ARE SMALL

  100. SO WHEN YOU MIX SHARED MUTABLE STATE WITH COMPLEXITY

  101. THE MUTABLE STATE MONSTER IS BORN ACTUAL PHOTO

  102. CHAPTER 3: THE PROPHET

  103. THERE ONCE WAS A PROPHET CALLED GORDON MOORE

  104. HE CO-FOUNDED A SEMICONDUCTOR COMPANY CALLED INTEL

  105. GORDON MOORE ACTUAL PHOTO

  106. IN 1965, HE MADE A PROPHECY

  107. THE NUMBER OF TRANSISTORS IN A DENSE INTEGRATED CIRCUIT DOUBLES

    APPROXIMATELY EVERY TWO YEARS GORDON MOORE MOORE’S LAW
  108. AND BEHOLD, THE PROPHECY WAS TRUE

  109. None
  110. BUT IN THE PAST DECADE, THE PROPHECY HASN’T HELD

  111. OUR COMPUTERS WON’T BECOME SIGNIFICANTLY FASTER EVERY YEAR

  112. WE CANNOT STUFF MORE TRANSISTORS INTO OUR PROCESSORS ANYMORE

  113. WE HAVE TO MAKE OUR PROGRAMS USE MULTIPLE CORES EFFECTIVELY

  114. OUR TOOLS SUCK

  115. WE NEED TO DO BETTER

  116. WE’RE JUST GOING TO HAVE TO..

  117. None
  118. CHAPTER 4: THE FELLOWSHIP OF THE FUNCTIONAL PROGRAMMERS

  119. JOHN MCCARTHY, ALONZO CHURCH, HASKELL CURRY, RICH HICKEY… ACTUAL GROUP

    PHOTO
  120. THEY WERE THINKING OF AN ALTERNATIVE WAY OF REPRESENTING COMPUTATION

  121. CAN WE REPRESENT PROGRAMS AS A SERIES OF DATA TRANSFORMATIONS

    INSTEAD OF A SERIES OF SEQUENTIAL DATA MUTATIONS?
  122. IMPERATIVE PROGRAM

  123. int[] numbers = {5,10,15};
 
 int sum() {
 int total

    = 0;
 
 for(int i=0; i<numbers.length ; i++) {
 total = total + numbers[i];
 }
 
 return total;
 }
  124. int[] numbers = {5,10,15};
 
 int sum() {
 int total

    = 0;
 
 for(int i=0; i<numbers.length ; i++) {
 total = total + numbers[i];
 }
 
 return total;
 }
  125. int[] numbers = {5,10,15};
 
 int sum() {
 int total

    = 0;
 
 for(int i=0; i<numbers.length ; i++) {
 total = total + numbers[i];
 }
 
 return total;
 }
  126. int[] numbers = {5,10,15};
 
 int sum() {
 int total

    = 0;
 
 for(int i=0; i<numbers.length ; i++) {
 total = total + numbers[i];
 }
 
 return total;
 }
  127. int[] numbers = {5,10,15};
 
 int sum() {
 int total

    = 0;
 
 for(int i=0; i<numbers.length ; i++) {
 total = total + numbers[i];
 }
 
 return total;
 }
  128. int[] numbers = {5,10,15};
 
 int sum() {
 int total

    = 0;
 
 for(int i=0; i<numbers.length ; i++) {
 total = total + numbers[i];
 }
 
 return total;
 }
  129. int[] numbers = {5,10,15};
 
 int sum() {
 int total

    = 0;
 
 for(int i=0; i<numbers.length ; i++) {
 total = total + numbers[i];
 }
 
 return total;
 }
  130. int[] numbers = {5,10,15};
 
 int sum() {
 int total

    = 0;
 
 for(int i=0; i<numbers.length ; i++) {
 total = total + numbers[i];
 }
 
 return total;
 } The result is 30
  131. FUNCTIONAL PROGRAM

  132. int compute() {
 return sum(sum(sum(0, 5), 10), 15);
 }
 


    int sum(int x, int y) {
 return x + y;
 }
  133. int compute() {
 return sum(sum(sum(0, 5), 10), 15);
 }
 


    int sum(int x, int y) {
 return x + y;
 }
  134. int compute() {
 return sum(sum(sum(0, 5), 10), 15);
 }
 


    int sum(int x, int y) {
 return x + y;
 }
  135. int compute() {
 return sum(sum(sum(0, 5), 10), 15);
 }
 


    int sum(int x, int y) {
 return x + y;
 }
  136. int compute() {
 return sum(sum(sum(0, 5), 10), 15);
 }
 


    int sum(int x, int y) {
 return x + y;
 }
  137. int compute() {
 return sum(sum(sum(0, 5), 10), 15);
 }
 


    int sum(int x, int y) {
 return x + y;
 } The result is still 30
  138. FUNCTIONAL PROGRAMMING IS ABOUT MODELLING OUR PROGRAMS IN TERMS OF

    EXPRESSIONS RATHER THAN STEP BY STEP INSTRUCTIONS
  139. THE IDEA IS TO BE AS DECLARATIVE AS POSSIBLE AND

    LET THE SYSTEM WORRY ABOUT LOW LEVEL DETAILS
  140. WE DON'T NEED TO KNOW EVERYTHING ABOUT FUNCTIONAL PROGRAMMING. WE

    JUST NEED TO STEAL SOME GOOD IDEAS
  141. IDEA 1: REFERENTIAL TRANSPARENCY

  142. REFERENTIAL TRANSPARENCY MEANS THERE IS NO DIFFERENCE BETWEEN THE VALUE

    AND THE REFERENCE TO A PIECE OF DATA
  143. Book book = new Book(“Vol 2”, “Green”);

  144. Book book = new Book(“Vol 2”, “Green”);

  145. Book book = new Book(“Vol 2”, “Green”); book.setTitle(“Vol 3");

  146. Book book = new Book(“Vol 2”, “Green”); book.setTitle(“Vol 3”); book.setColour(“Blue");

  147. Book book = new Book(“Vol 2”, “Green”); book.setTitle(“Vol 3”); book.setColour(“Blue");

  148. Book book = new Book(“Vol 2”, “Green”); book.setTitle(“Vol 3”); book.setColour(“Blue");

    The same book object can have different values at different points in time
  149. Book book = new Book(“Vol 2”, “Green”); book.setTitle(“Vol 3”); book.setColour(“Blue");

    Not referentially transparent X
  150. TO ACHIEVE REFERENTIAL TRANSPARENCY, WE NEED TO STEAL ANOTHER IDEA

  151. IDEA 2: IMMUTABILITY

  152. IMMUTABILITY MEANS DATA ONCE CREATED CANNOT BE MODIFIED

  153. Book book = new Book(“Vol 2”, “Green”);

  154. Book book = new Book(“Vol 2”, “Green”);

  155. Book book = new Book(“Vol 2”, “Green”); book.setTitle(“Vol 3”);

  156. Book book = new Book(“Vol 2”, “Green”); book.setTitle(“Vol 3”); Can’t

    change immutable data X
  157. INSTEAD OF MODIFYING, WE CAN MAKE A WHOLE NEW OBJECT

    WITH OUR NEW PROPERTIES
  158. MUTABLE BOOK STORE

  159. public class BookStore {
 private List<String> books;
 
 public BookStore(final

    List<String> books) {
 this.books = books;
 }
 
 public void addBooks(List<String> additionalBooks) {
 this.books.addAll(additionalBooks);
 }
 
 public List<String> getBooks() {
 return books;
 }
 }
  160. public class BookStore {
 private List<String> books;
 
 public BookStore(final

    List<String> books) {
 this.books = books;
 }
 
 public void addBooks(List<String> additionalBooks) {
 this.books.addAll(additionalBooks);
 }
 
 public List<String> getBooks() {
 return books;
 }
 }
  161. public class BookStore {
 private List<String> books;
 
 public BookStore(final

    List<String> books) {
 this.books = books;
 }
 
 public void addBooks(List<String> additionalBooks) {
 this.books.addAll(additionalBooks);
 }
 
 public List<String> getBooks() {
 return books;
 }
 }
  162. public class BookStore {
 private List<String> books;
 
 public BookStore(final

    List<String> books) {
 this.books = books;
 }
 
 public void addBooks(List<String> additionalBooks) {
 this.books.addAll(additionalBooks);
 }
 
 public List<String> getBooks() {
 return books;
 }
 }
  163. public class BookStore {
 private List<String> books;
 
 public BookStore(final

    List<String> books) {
 this.books = books;
 }
 
 public void addBooks(List<String> additionalBooks) {
 this.books.addAll(additionalBooks);
 }
 
 public List<String> getBooks() {
 return books;
 }
 }
  164. public class BookStore {
 private List<String> books;
 
 public BookStore(final

    List<String> books) {
 this.books = books;
 }
 
 public void addBooks(List<String> additionalBooks) {
 this.books.addAll(additionalBooks); <- Mutation
 }
 
 public List<String> getBooks() {
 return books;
 }
 }
  165. public class BookStore {
 private List<String> books;
 
 public BookStore(final

    List<String> books) {
 this.books = books;
 }
 
 public void addBooks(List<String> additionalBooks) {
 this.books.addAll(additionalBooks);
 }
 
 public List<String> getBooks() {
 return books;
 }
 } How do we make this immutable?
  166. IMMUTABLE BOOK STORE

  167. public class BookStore {
 private final List<String> books;
 
 public

    BookStore(final List<String> books) {
 this.books = books;
 }
 
 public BookStore addBooks(List<String> additionalBooks) {
 List<String> newBooks = getBooks();
 
 newBooks.addAll(additionalBooks);
 
 return new BookStore(newBooks);
 }
 
 public List<String> getBooks() {
 List<String> copy = new ArrayList<>();
 for (String book : books) {
 copy.add(book);
 }
 return copy;
 }
 }
  168. public class BookStore {
 private final List<String> books;
 
 public

    BookStore(final List<String> books) {
 this.books = books;
 }
 
 public BookStore addBooks(List<String> additionalBooks) {
 List<String> newBooks = getBooks();
 
 newBooks.addAll(additionalBooks);
 
 return new BookStore(newBooks);
 }
 
 public List<String> getBooks() {
 List<String> copy = new ArrayList<>();
 for (String book : books) {
 copy.add(book);
 }
 return copy;
 }
 }
  169. public class BookStore {
 private final List<String> books;
 
 public

    BookStore(final List<String> books) {
 this.books = books;
 }
 
 public BookStore addBooks(List<String> additionalBooks) {
 List<String> newBooks = getBooks();
 
 newBooks.addAll(additionalBooks);
 
 return new BookStore(newBooks);
 }
 
 public List<String> getBooks() {
 List<String> copy = new ArrayList<>();
 for (String book : books) {
 copy.add(book);
 }
 return copy;
 }
 }
  170. public class BookStore {
 private final List<String> books;
 
 public

    BookStore(final List<String> books) {
 this.books = books;
 }
 
 public BookStore addBooks(List<String> additionalBooks) {
 List<String> newBooks = getBooks();
 
 newBooks.addAll(additionalBooks);
 
 return new BookStore(newBooks);
 }
 
 public List<String> getBooks() {
 List<String> copy = new ArrayList<>();
 for (String book : books) {
 copy.add(book);
 }
 return copy;
 }
 }
  171. public class BookStore {
 private final List<String> books;
 
 public

    BookStore(final List<String> books) {
 this.books = books;
 }
 
 public BookStore addBooks(List<String> additionalBooks) {
 List<String> newBooks = getBooks();
 
 newBooks.addAll(additionalBooks);
 
 return new BookStore(newBooks);
 }
 
 public List<String> getBooks() {
 List<String> copy = new ArrayList<>();
 for (String book : books) { <- Deep copy
 copy.add(book);
 }
 return copy;
 }
 }
  172. public class BookStore {
 private final List<String> books;
 
 public

    BookStore(final List<String> books) {
 this.books = books;
 }
 
 public BookStore addBooks(List<String> additionalBooks) {
 List<String> newBooks = getBooks();
 
 newBooks.addAll(additionalBooks);
 
 return new BookStore(newBooks);
 }
 
 public List<String> getBooks() {
 List<String> copy = new ArrayList<>();
 for (String book : books) {
 copy.add(book);
 }
 return copy; <- Return deep copy, not the original
 }
 }
  173. public class BookStore {
 private final List<String> books;
 
 public

    BookStore(final List<String> books) {
 this.books = books;
 }
 
 public BookStore addBooks(List<String> additionalBooks) {
 List<String> newBooks = getBooks();
 
 newBooks.addAll(additionalBooks);
 
 return new BookStore(newBooks);
 }
 
 public List<String> getBooks() {
 List<String> copy = new ArrayList<>();
 for (String book : books) {
 copy.add(book);
 }
 return copy;
 }
 }
  174. public class BookStore {
 private final List<String> books;
 
 public

    BookStore(final List<String> books) {
 this.books = books;
 }
 
 public BookStore addBooks(List<String> additionalBooks) {
 List<String> newBooks = getBooks(); <- Get deep copy
 
 newBooks.addAll(additionalBooks);
 
 return new BookStore(newBooks);
 }
 
 public List<String> getBooks() {
 List<String> copy = new ArrayList<>();
 for (String book : books) {
 copy.add(book);
 }
 return copy;
 }
 }
  175. public class BookStore {
 private final List<String> books;
 
 public

    BookStore(final List<String> books) {
 this.books = books;
 }
 
 public BookStore addBooks(List<String> additionalBooks) {
 List<String> newBooks = getBooks();
 
 newBooks.addAll(additionalBooks); <- Add to deep copy 
 
 return new BookStore(newBooks);
 }
 
 public List<String> getBooks() {
 List<String> copy = new ArrayList<>();
 for (String book : books) {
 copy.add(book);
 }
 return copy;
 }
 }
  176. public class BookStore {
 private final List<String> books;
 
 public

    BookStore(final List<String> books) {
 this.books = books;
 }
 
 public BookStore addBooks(List<String> additionalBooks) {
 List<String> newBooks = getBooks();
 
 newBooks.addAll(additionalBooks);
 
 return new BookStore(newBooks); <- Return a new BookStore
 }
 
 public List<String> getBooks() {
 List<String> copy = new ArrayList<>();
 for (String book : books) {
 copy.add(book);
 }
 return copy;
 }
 }
  177. STORE 1

  178. STORE 1 ADD SOME BOOKS

  179. STORE 1 ADD SOME BOOKS STORE 2

  180. The original book store is always the original book store

  181. Referential Transparency!

  182. Referential Transparency!

  183. HOW DOES THIS STUFF MAKE CONCURRENCY SAFER IN OUR APPS?

  184. BOOK STORE

  185. BOOK STORE

  186. BOOK STORE UI Thread

  187. BOOK STORE UI Thread Observable.just(bookStore)
 .map(addSomeBooks())
 .map(sortAllBooks())
 .subscribeOn(Schedulers.io())
 .observeOn(AndroidSchedulers.mainThread())
 .subscribe(


    // Update list with new BookStore
 );
  188. BOOK STORE UI Thread Observable.just(bookStore)
 .map(addSomeBooks())
 .map(sortAllBooks())
 .subscribeOn(Schedulers.io())
 .observeOn(AndroidSchedulers.mainThread())
 .subscribe(


    // Update list with new BookStore
 );
  189. BOOK STORE UI Thread Observable.just(bookStore)
 .map(addSomeBooks())
 .map(sortAllBooks())
 .subscribeOn(Schedulers.io())
 .observeOn(AndroidSchedulers.mainThread())
 .subscribe(


    // Update list with new BookStore
 );
  190. BOOK STORE UI Thread Observable.just(bookStore)
 .map(addSomeBooks())
 .map(sortAllBooks())
 .subscribeOn(Schedulers.io())
 .observeOn(AndroidSchedulers.mainThread())
 .subscribe(


    // Update list with new BookStore
 );
  191. BOOK STORE UI Thread Observable.just(bookStore)
 .map(addSomeBooks())
 .map(sortAllBooks())
 .subscribeOn(Schedulers.io())
 .observeOn(AndroidSchedulers.mainThread())
 .subscribe(


    // Update list with new BookStore
 );
  192. BOOK STORE UI Thread Observable.just(bookStore)
 .map(addSomeBooks())
 .map(sortAllBooks())
 .subscribeOn(Schedulers.io())
 .observeOn(AndroidSchedulers.mainThread())
 .subscribe(


    // Update list with new BookStore
 );
  193. BOOK STORE UI Thread Observable.just(bookStore)
 .map(addSomeBooks())
 .map(sortAllBooks())
 .subscribeOn(Schedulers.io())
 .observeOn(AndroidSchedulers.mainThread())
 .subscribe(


    // Update list with new BookStore
 );
  194. BOOK STORE UI Thread Observable.just(bookStore)
 .map(addSomeBooks())
 .map(sortAllBooks())
 .subscribeOn(Schedulers.io())
 .observeOn(AndroidSchedulers.mainThread())
 .subscribe(


    // Update list with new BookStore
 ); BOOK STORE 1 Background Thread
  195. BOOK STORE UI Thread Observable.just(bookStore)
 .map(addSomeBooks())
 .map(sortAllBooks())
 .subscribeOn(Schedulers.io())
 .observeOn(AndroidSchedulers.mainThread())
 .subscribe(


    // Update list with new BookStore
 ); BOOK STORE 1 Background Thread No incompletely modified data
  196. BOOK STORE UI Thread BOOK STORE 1 Background Thread Meanwhile,

    Another background thread writes to our store
  197. BOOK STORE UI Thread BOOK STORE 1 Background Thread It

    gets it’s own copy do whatever it wants BOOK STORE FOR THREAD 2 Background Thread 2
  198. BOOK STORE UI Thread BOOK STORE 1 Background Thread No

    lock based synchronization necessary BOOK STORE FOR THREAD 2 Background Thread 2
  199. BOOK STORE UI Thread Observable.just(bookStore)
 .map(addSomeBooks())
 .map(sortAllBooks())
 .subscribeOn(Schedulers.io())
 .observeOn(AndroidSchedulers.mainThread())
 .subscribe(


    // Update list with new BookStore
 ); BOOK STORE 1 Background Thread BOOK STORE 2
  200. UI Thread Observable.just(bookStore)
 .map(addSomeBooks())
 .map(sortAllBooks())
 .subscribeOn(Schedulers.io())
 .observeOn(AndroidSchedulers.mainThread())
 .subscribe(
 // Update

    list with new BookStore
 ); BOOK STORE 2
  201. UI Thread BOOK STORE 2

  202. BUT MY POOR GARBAGE COLLECTOR!

  203. CORRECTNESS IS OFTEN MORE IMPORTANT THAT RAW PERFORMANCE

  204. YOU CAN USE IMMUTABILITY ONLY WHERE YOU EXPECT CONCURRENCY

  205. CHAPTER 5: A NEW AGE

  206. FUNCTIONAL IS GETTING POPULAR

  207. None
  208. FRONTEND

  209. None
  210. BACKEND

  211. None
  212. WHAT ABOUT GOOD OLD ANDROID?

  213. JAVA 8 ON ANDROID INTRODUCED STREAMS, LAMBDAS AND METHOD REFERENCES

  214. WE HAVE RX TO TRANSFORM DATA

  215. WE HAVE KOTLIN WHICH HAS FIRST CLASS SUPPORT FOR IMMUTABLE

    DATA
  216. YOU DON’T HAVE TO DO IT ALL AT ONCE

  217. AND YOU DON’T HAVE TO DO IT ALONE

  218. THE FUTURE IS BRIGHT

  219. THANK YOU! @anupcowkur