b3cc concurrency 05 software transactional memory 1
play

B3CC: Concurrency 05: Software Transactional Memory (1) Trevor L. - PowerPoint PPT Presentation

B3CC: Concurrency 05: Software Transactional Memory (1) Trevor L. McDonell Utrecht University, B2 2020-2021 Announcement From next week (Nov 30) we will o ff er the online werkcollege: - Monday 13:15 - 15:00 - Thursday 9:00 - 10:45 As


  1. B3CC: Concurrency 05: Software Transactional Memory (1) Trevor L. McDonell Utrecht University, B2 2020-2021

  2. Announcement • From next week (Nov 30) we will o ff er the online werkcollege: - Monday 13:15 - 15:00 - Thursday 9:00 - 10:45 • As well as the on-campus werkcollege at the usual time: - Tuesday 15:15 - 17:00 2

  3. Critical sections 3

  4. Example: bank accounts • Model bank accounts and operations like withdrawing, depositing, and transferring money between accounts - It should not be possible to observe a state where, during a transfer, money has been withdrawn from one account but yet to be deposited into the target account Thread A Thread B $150 $200 Account 1 Account 2 Account 3 $500 $300 $200 4

  5. Example: bank accounts Thread A Thread B $150 $200 Account 1 Account 2 Account 3 $500 $300 $200 • Thread A: • Thread B: 5

  6. Example: bank accounts Thread A Thread B $150 $200 Account 1 Account 2 Account 3 $500 $300 $200 • Thread A: • Thread B: - Read balance of account 2 6

  7. Example: bank accounts Thread A Thread B $150 $200 Account 1 Account 2 Account 3 $500 $300 $200 • Thread A: • Thread B: - Read balance of account 2 - Check for sufficient funds 7

  8. Example: bank accounts Thread A Thread B $150 $200 Account 1 Account 2 Account 3 $500 $300 $200 • Thread A: • Thread B: - Read balance of account 2 - Check for sufficient funds - Read balance of account 2 8

  9. Example: bank accounts Thread A Thread B $150 $200 Account 1 Account 2 Account 3 $500 $300 $200 • Thread A: • Thread B: - Read balance of account 2 - Check for sufficient funds - Read balance of account 2 - Check for sufficient funds 9

  10. Example: bank accounts Thread A Thread B $150 $200 Account 1 Account 2 Account 3 $500 $100 $400 • Thread A: • Thread B: - Read balance of account 2 - Check for sufficient funds - Read balance of account 2 - Check for sufficient funds - Update balance of account 2 10

  11. Example: bank accounts Thread A Thread B $150 $200 Account 1 Account 2 Account 3 $650 $150 $400 • Thread A: • Thread B: - Read balance of account 2 - Check for sufficient funds - Read balance of account 2 - Check for sufficient funds - Update balance of account 2 - Update balance of account 2 11

  12. Attempt #1 • The basic idea: type Account = IORef Int deposit ::; Int ->. Account ->. IO () deposit amount acc = do balance <.- readIORef acc writeIORef acc (balance + amount) withdraw ::; Int ->. Account ->. IO () withdraw amount acc = deposit (-amount) acc 12

  13. Attempt #2 • Use locks so that updates are atomic: type Account = MVar Int deposit ::; Int ->. Account ->. IO () deposit amount acc = modifyMVar_ acc $ \balance ->. return (balance + amount)) transfer ::; Int ->. Account ->. Account ->. IO () 
 transfer amount from to = do 
 withdraw amount from 
 inconsistent state! deposit amount to 13

  14. Attempt #3 • We need to implement transfer di ff erently type Account = MVar Int transfer ::; Int ->. Account ->. Account ->. IO () transfer amount from to = modifyMVar_ from $ \fromBalance ->. do modifyMVar_ to $ \toBalance ->. return (toBalance + amount) return (fromBalance - amount) P 0 : P 1 : transfer 100 acc1 acc2 transfer 200 acc2 acc1 14

  15. Attempt #4 • Take locks in an a fixed (but arbitrary) order; release in the opposite order type Account = MVar Int transfer ::; Int ->. Account ->. Account ->. IO () transfer amount from to = if from < to then modifyMVar_ from $ \fromBalance ->. modifyMVar_ to $ \toBalance ->. ..../ else modifyMVar_ to $ \toBalance ->. modifyMVar_ from $ \fromBalance ->. ..../ 15

  16. Extending the example • What happens if we want to… - Block (wait) until the from account has sufficient funds? - Withdraw from a second account if the first does not have sufficient funds? • I hold locks #3 and #5 • And now need to acquire lock #2, or #4 or… 16

  17. Locks are bad • Problems with locks include: - Taking too few locks - Taking too many locks • Inhibits concurrency (at best) or causes deadlock (at worst) - Taking the wrong locks - Taking locks in the wrong order - Error recovery - Lost wake-ups or erroneous retries 17

  18. Locks are bad • The killer: - Locks don’t support modular programming - We needed to create a new function transfer , rather than using the (correctly working) functions withdraw and deposit 18

  19. Atomic blocks 19

  20. An alternative • The idea: - Garbage collectors allow us to program without malloc and free; 
 Can we do the same for locks? What would that look like? - Modular concurrency! - Locks are pessimistic; let’s be optimistic instead 20

  21. Software transactional memory • A technique for implementing atomic blocks - Atomicity: effects become visible to other threads all at once - Isolation: cannot see the effects of other threads - Use a different type to wrap operations whose effects can be undone if necessary (more on this later) import Control.Concurrent.STM data STM a --. abstract instance Monad STM --. among other things atomically ::; STM a ->. IO a 21

  22. Software transactional memory • Sharing state - Instead of IORef , we use TVar as a transactional variable - Basic interface: import Control.Concurrent.STM.TVar newTVar ::; a ->. STM (TVar a) readTVar ::; TVar a ->. STM a writeTVar ::; TVar a ->. a ->. STM () 22

  23. Software transactional memory • Sharing state - Instead of MVar we have an equivalent TMVar - A variable is either full or empty: threads wait for the appropriate state - Basic interface: import Control.Concurrent.STM.TMVar newTMVar ::; a ->. STM (TMVar a) newEmptyTMVar ::; STM (TMVar) readTMVar ::; TMVar a ->. STM a writeTMVar ::; TMVar a ->. a ->. STM () 23

  24. Revisiting accounts • STM actions are composed together in the same way as IO actions type Account = TVar Int deposit ::; Int ->. Account ->. STM () deposit amount account = do balance <.- readTVar account writeTVar (balance + amount) account withdraw ::; Int ->. Account ->. STM () withdraw amount = deposit (-amount) 24

  25. Revisiting accounts • STM actions are executed as a single, isolated atomic block transfer ::; Int ->. Account ->. Account ->. IO () transfer amount from to = atomically $ do withdraw amount from deposit amount to 25

  26. STM • Types are used to isolate transactional actions from arbitrary IO actions - To get from STM to IO we have to execute the entire action atomically - Can’t mix monads! bad ::; Int ->. Account ->. STM () bad amount account = do putStrLn “withdrawing!” --. ::; IO () withdraw amount account --. ::; STM () good ::; Int ->. Account ->. IO () good amount account = do putStrLn “withdrawing!” --. ::; IO () atomically $ withdraw amount account --. ::; IO () 26

  27. Implementing transactional memory • How to implement atomically - Single global lock? - Instead: optimistic execution, without taking any locks • At the start of the atomic block begin a thread local transaction log - Each writeTVar records the address and the new value to the log - Each readTVar searches the log and • Takes the value of an earlier writeTVar; or • Reads the TVar and records the value into the log 27

  28. Implementing transactional memory • At the end of the atomic block the transaction log must be validated - Checks each readTVar in the log matches the current value - If successful all writeTVar recorded in the log are committed to the real TVars - The validate and commit steps must be truly atomic 28

  29. Implementing transactional memory • What if validation fails? - The operation executed with an inconsistent view of memory - Re-execute the transaction with a new transaction log • Since none of the writes are committed to memory, this is safe to do • It is critical that the atomic block contains no actions other than reads and writes to TVars atomically $ do x <.- readTVar xv y <.- readTVar yv if x > y then brexit --. ::; IO () side effects! else return () 29

  30. Summary (so far) • STM gives us: - Atomic transactions for shared memory - Encapsulation of concurrent code - Help avoid common locking problems • But… - Just like garbage collection, is no silver bullet - Can not solve all problems: e.g. starvation & contention 30

  31. tot ziens Photo by JC Gellidon

Download Presentation
Download Policy: The content available on the website is offered to you 'AS IS' for your personal information and use only. It cannot be commercialized, licensed, or distributed on other websites without prior consent from the author. To download a presentation, simply click this link. If you encounter any difficulties during the download process, it's possible that the publisher has removed the file from their server.

Recommend


More recommend