Advertisement
timothy235

sicp-3-4-2-mechanisms-for-controlling-concurrency

Mar 4th, 2017
203
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Racket 10.13 KB | None | 0 0
  1. #lang racket
  2. (require racket/mpair)
  3.  
  4. ;; The book provides most of the code to make a serializer, but it's not complete
  5. ;; because that would be machine-dependent.  So here is a version using Racket
  6. ;; semaphores:
  7.  
  8. (define (make-serializer)
  9.   (define sema (make-semaphore 1))
  10.   (lambda (p)
  11.     (define (serialized-p arg)
  12.       (call-with-semaphore sema p false arg))
  13.     serialized-p))
  14.  
  15. ;;;;;;;;;;
  16. ;; 3.39 ;;
  17. ;;;;;;;;;;
  18.  
  19. #|
  20. x = 10
  21. P1: read x twice, take the product, write the product
  22. P2: read x once, add 1, write the sum
  23.  
  24. If we serialize all of P2, but only the "read x twice and take the product"
  25. part of P1, then three possibilities remain:
  26.  
  27. 101: P1 runs, then P2 runs
  28. 121: P2 runs, then P1 runs
  29. 100: P1 reads x twice and takes the product, then P2 runs, then P1 sets x
  30.  
  31. 110 is not possible because we cannot interleave between the two reads of P1,
  32. and 11 is not possible because we cannot interleave between the read and write
  33. of P2.
  34. |#
  35.  
  36. ;;;;;;;;;;
  37. ;; 3.40 ;;
  38. ;;;;;;;;;;
  39.  
  40. #|
  41. P1 is read x twice, take the product, and write the product.
  42. P2 is read x three times, take the product, and write the product.
  43.  
  44. Describe P1 as the sequence of four atomic operations: r1, r2, p1, w1,
  45. namely, two reads, a multiplication, and a write.
  46.  
  47. Describe P2 as the sequence of five atomic operations: s1, s2, s3, p2, w2,
  48. namely, three reads, a multiplication, and a write.
  49.  
  50. Without serialization, we can interleave these nine operations in any
  51. order we want, so long as the four operations for P1 are in order and the
  52. five operations for P2 are in order.
  53. |#
  54.  
  55. (define (sublist? lst1 lst2)
  56.   ;  All the elements of lst1 appear in lst2 and in the same order.
  57.   (define (loop xs ys)
  58.     (cond [(empty? xs) true]
  59.           [else
  60.             (define memb (member (first xs) ys))
  61.             (if memb
  62.               (loop (rest xs) memb)
  63.               false)]))
  64.   (loop lst1 lst2))
  65.  
  66. (define (interleaved-sequences as bs)
  67.   (sequence->list (sequence-filter
  68.                     (lambda (perm) (and (sublist? as perm)
  69.                                         (sublist? bs perm)))
  70.                     (in-permutations (append as bs)))))
  71.  
  72. (define (result ops)
  73.   (define x 10)
  74.   (define r1 0)
  75.   (define r2 0)
  76.   (define p1 0)
  77.   (define s1 0)
  78.   (define s2 0)
  79.   (define s3 0)
  80.   (define p2 0)
  81.   (define (process! op)
  82.     (cond [(eq? op 'r1) (set! r1 x)]
  83.           [(eq? op 'r2) (set! r2 x)]
  84.           [(eq? op 'p1) (set! p1 (* r1 r2))]
  85.           [(eq? op 'w1) (set! x p1)]
  86.           [(eq? op 's1) (set! s1 x)]
  87.           [(eq? op 's2) (set! s2 x)]
  88.           [(eq? op 's3) (set! s3 x)]
  89.           [(eq? op 'p2) (set! p2 (* s1 s2 s3))]
  90.           [(eq? op 'w2) (set! x p2)]
  91.           [else (error "Unknown op -- PROCESS!" op)]))
  92.   (map process! ops)
  93.   x)
  94.  
  95. (define seqs ; there are 126 such interleaved sequences
  96.   (interleaved-sequences '(r1 r2 p1 w1) '(s1 s2 s3 p2 w2)))
  97. (define possibilities
  98.   (remove-duplicates
  99.     (for/list ([ops seqs])
  100.               (result ops))))
  101. possibilities
  102. ;; '(1000000 100000 10000 1000 100)
  103.  
  104. ;; So without serialization, there are five possibilities, but with serialization,
  105. ;; there is only one, namely 10 ^ 6.
  106.  
  107. ;;;;;;;;;;
  108. ;; 3.41 ;;
  109. ;;;;;;;;;;
  110.  
  111. ;; I don't see any reason to serialize a read operation.  The read doesn't change
  112. ;; anything, nor does it have component parts that need to be run consecutively.
  113.  
  114. ;;;;;;;;;;
  115. ;; 3.42 ;;
  116. ;;;;;;;;;;
  117.  
  118. ;; I don't think it matters whether we create the serialized procedure at account
  119. ;; creation or when dispatch is called.  The only thing that matters is that all
  120. ;; the serialized procedures use the same mutex, so each is protected from the
  121. ;; others.
  122.  
  123. ;;;;;;;;;;
  124. ;; 3.43 ;;
  125. ;;;;;;;;;;
  126.  
  127. #|
  128. Double serializing the exchange procedure, using both accounts' serializers,
  129. protects the exchange operations from being interleaved with other account
  130. operations from either account.  This makes exchange atomic.  So its behavior
  131. will be as expected.
  132.  
  133. With the original definition of exchange, the exchange operation will not be
  134. atomic, but it will be composed of four atomic operations, two reads, a
  135. withdrawal, and a deposit.
  136.  
  137. To see how the original exchange definition might not preserve the three
  138. balances, consider the following three exchanges:
  139.  
  140. acct1 = 10
  141. acct2 = 20
  142. acct3 = 30
  143.  
  144. P1: exchange accounts 1 and 2
  145. P2: exchange accounts 2 and 3
  146. P3: exchange accounts 1 and 3
  147.  
  148. The original exchange allows us to interleave P3 between reads of P1 and P2:
  149.  
  150. P1 reads acct1 = 10
  151. P2 reads acct2 = 20
  152. P3 makes acct1 = 30 and acct3 = 10
  153. P1 reads acct2 = 20
  154. P2 reads acct3 = 10
  155. P1 adds 10 to acct1 and subtracts 10 from acct2, now acct1 = 40 and acc2 = 10
  156. P2 subtracts 10 from acct2 and adds 10 to acct3, now acct2 = 0 and acct3 = 20
  157.  
  158. Final balances:
  159. acct1 = 40
  160. acct2 = 0
  161. acct3 = 20
  162.  
  163. However the sum of all three balances cannot change.  This is because each
  164. exchange adds and removes a fixed amount between accounts.  So total deposits
  165. will always equal total withdrawals.
  166. |#
  167.  
  168. ;;;;;;;;;;
  169. ;; 3.44 ;;
  170. ;;;;;;;;;;
  171.  
  172. ;; The problem with exchange was that balances could be mutated between reads.
  173. ;; Here there are no reads.  So this is OK.
  174.  
  175. ;;;;;;;;;;
  176. ;; 3.45 ;;
  177. ;;;;;;;;;;
  178.  
  179. (define (exchange account1 account2)
  180.   (define difference (- (account1 'balance) (account2 'balance)))
  181.   ((account1 'withdraw) difference)
  182.   ((account2 'deposit) difference))
  183.  
  184. (define (serialized-exchange account1 account2)
  185.   (define serializer1 (account1 'serializer))
  186.   (define serializer2 (account2 'serializer))
  187.   ((serializer1 (serializer2 (exchange)))
  188.    account1
  189.    account2))
  190.  
  191. ;; The problem is that account operations in serialized-exchange are triply
  192. ;; serialized, once by the foreign account and twice by the native account, and a
  193. ;; procedure that is serialized twice with the same mutex will hang the program.
  194.  
  195. ;; example
  196.  
  197. (define ser (make-serializer))
  198. (define serialized-sqr (ser sqr))
  199. (define twice-serialized-sqr (ser serialized-sqr))
  200. (sqr 2)
  201. ;; 4
  202. (serialized-sqr 2)
  203. ;; 4
  204. ;; (twice-serialized-sqr 2)
  205. ;; ;; . . user break ; the repl hung
  206.  
  207. ;;;;;;;;;;
  208. ;; 3.46 ;;
  209. ;;;;;;;;;;
  210.  
  211. ;; The mutex is free when false, busy when true.
  212.  
  213. (define (make-mutex)
  214.   (define cell (list false))
  215.   (define (the-mutex m)
  216.     (cond [(eq? m 'acquire)
  217.            ; If mutex busy, try again.
  218.            ; If mutex free, test-and-set! marked it busy, so do nothing.
  219.            (when (test-and-set! cell)
  220.              (the-mutex 'acquire))]
  221.           ; Mark the mutex free.
  222.           [(eq? m 'release)
  223.            (clear! cell)]))
  224.   the-mutex)
  225.  
  226. (define (clear! cell)
  227.   ; Set cell to false, making mutex free.
  228.   (set-mcar! cell false))
  229.  
  230. (define (test-and-set! cell)
  231.   ; If mutex busy, cell is true, do nothing to cell, and return true.
  232.   ; If mutex free, cell is false, set cell to true, and return false.
  233.   (cond [(mcar cell)
  234.         true]
  235.         [else
  236.           (set-mcar! cell true)
  237.           false]))
  238.  
  239. ;; test-and-set! is comprised of two operations, a read and a write.  In ordinary
  240. ;; code, this is not atomic.  So one operation could perform its read and write
  241. ;; between the read and write of another operation, allowing both operations to
  242. ;; acquire the mutex.
  243.  
  244. ;;;;;;;;;;
  245. ;; 3.47 ;;
  246. ;;;;;;;;;;
  247.  
  248. ;; SEMAPHORES IN TERMS OF MUTEXES
  249.  
  250. ;; Use the count to allow only n processes at a time, and use the mutex to protect
  251. ;; the semaphore operations.
  252.  
  253. (define (make-semaphore1 n)
  254.   (define mutex (make-mutex))
  255.   (define number 0)
  256.   (define (the-semaphore m)
  257.     (cond [(eq? m 'acquire)
  258.            (mutex 'acquire)
  259.            (cond [(< number n)
  260.                   (set! number (add1 number))
  261.                   (mutex 'release)]
  262.                  [else
  263.                    (mutex 'release)
  264.                    (the-semaphore 'acquire)])]
  265.           [(eq? m 'release)
  266.            (mutex 'acquire)
  267.            (set! number (sub1 number))
  268.            (mutex 'release)]))
  269.   the-semaphore)
  270.  
  271. ;; SEMAPHORES IN TERMS OF ATOMIC TEST-AND-SET!
  272.  
  273. (define (make-semaphore2 n)
  274.   (define cell (list false))
  275.   (define number 0)
  276.   (define (the-semaphore m)
  277.     (cond [(eq? m 'acquire)
  278.            (when (test-and-set! cell)
  279.              (the-semaphore 'acquire))
  280.            (cond [(< number n)
  281.                   (set! number (add1 number))
  282.                   (clear! cell)]
  283.                  [else
  284.                    (clear! cell)
  285.                    (the-semaphore 'acquire)])]
  286.           [(eq? m 'release)
  287.            (when (test-and-set! cell)
  288.              (the-semaphore 'release))
  289.            (set! number (sub1 number))
  290.            (clear! cell)]))
  291.   the-semaphore)
  292.  
  293. ;;;;;;;;;;
  294. ;; 3.48 ;;
  295. ;;;;;;;;;;
  296.  
  297. (define (make-new-account balance account-number)
  298.   (define (withdraw amount)
  299.     (cond [(>= balance amount)
  300.            (set! balance (- balance amount))
  301.            balance]
  302.           [else "Insufficient funds"]))
  303.   (define (deposit amount)
  304.     (set! balance (+ balance amount))
  305.     balance)
  306.   (define serializer (make-serializer))
  307.   (define (dispatch m)
  308.     (cond [(eq? m 'withdraw) withdraw]
  309.           [(eq? m 'deposit) deposit]
  310.           [(eq? m 'balance) balance]
  311.           [(eq? m 'serializer) serializer]
  312.           [(eq? m 'account-number) account-number]
  313.           [else (error "Unknown request -- MAKE-NEW-ACCOUNT" m)]))
  314.   dispatch)
  315.  
  316. (define (new-exchange account1 account2)
  317.   (define n1 (account1 'account-number))
  318.   (define n2 (account2 'account-number))
  319.   (define s1 (account1 'serializer))
  320.   (define s2 (account2 'serializer))
  321.   (if (< n1 n2)
  322.     ((s2 (s1 exchange))
  323.      account1
  324.      account2)
  325.     ((s1 (s2 exchange))
  326.      account1
  327.      account2)))
  328.  
  329. ;; Deadlock occurred when one process had the mutex for account1 while the other
  330. ;; process had the mutex for account2, blocking each other.  But with this
  331. ;; exchange operation, both would try to acquire the mutex for the lower numbered
  332. ;; account first.  So they couldn't block each other.
  333.  
  334. ;;;;;;;;;;
  335. ;; 3.49 ;;
  336. ;;;;;;;;;;
  337.  
  338. ;; Imagine a bank trader that uses money from several accounts
  339. ;; non-deterministically.  He places trades from a master account, and behind the
  340. ;; scenes money is transferred between sub-accounts, based on the bank's exact
  341. ;; needs that day.  In this scenario two traders could still deadlock.
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement