Vous êtes sur la page 1sur 5

3/14/13

Memria transacional de so1ware


(STM)

Memria
Transacional

Regies da memria usadas dentro de transaes

Alterna<va ao uso de excluso mtua


!

Ainda um tpico de pesquisa


!

Lembrando: MVars so zonas de excluso mtua


Mas Haskell tem uma implementao robusta

Memria transacional tambm pode ser


implementada em hardware

Por que memria transacional?

Menos complicao para o programador


!

Pacote Control.Concurrent.STM

Transaes so definidas pela mnada STM

STM => atomicidade + isolamento


!

Travas so muito diMceis de gerenciar

Mais sobre STM

No h bloqueio (quase)
!

fcil compor transaes


Logo, no h deadlocks

Similar a IO

atomically :: STM a -> IO a

Uma transao no pode realizar operaes de entrada e


sada
E comunicao entre threads precisa ser controlada

novidade! :)
!

Mas pode ser a pr<ca daqui a alguns anos

Exemplo simplssimo

STM em ao

-- thread T1
atomically (do x1 < readTVar bal
writeTVar bal (x1+10)
)
-- thread T2
atomically (do x2 < readTVar bal
writeTVar bal (x2+2)
)

Variveis compar<lhadas: TVars


! Usadas apenas dentro de blocos atmicos
! E se as duas threads tentarem escrever em bal?

T1

T2

x2 <- readTVar bal

3/14/13

STM em ao

STM em ao
T1

T1

x1 <- readTVar bal

1
T2

T2

11

writeTVar bal x2 + 10

Cada transao mantm uma cpia da varivel!

STM em ao

STM em ao
T1

T1

writeTVar bal x1 + 1

T2

11

T2

Fim da
transao
de T2!

STM em ao

STM em ao

Transao
de T1
abortada!
T1

writeTVar bal x1 + 1

T1

11

x1 <- readTVar bal

T2
A transao
ento
reiniciada!

3/14/13

STM em ao

STM em ao
T1

13

writeTVar bal (x1 + 2)

Algumas denies importantes


data TVar a
readTVar :: TVar a -> STM a
writeTVar :: TVar a > a -> STM ()
newTVar :: a -> STM (TVar a)
retry :: STM a
orElse :: STM a -> STM a > STM a

Contador transacional
oper :: (Int->Int->Int) -> TVar Int ->
MVar Int -> Int -> IO()
oper op cont fim 0
= do f <- takeMVar fim
putMVar fim (f-1)
oper op cont fim num
= do v <- atomically (readTVar cont)
atomically (writeTVar cont (op v 1))
oper op cont fim (num-1)

Cdigo rodando...

T1

13

Fim da
transao
de T2!

Contador transacional
...
import Control.Concurrent.STM
main :: IO ()
main = do contador <- atomically (newTVar 0)
fim <- newMVar 2
forkIO (oper (+) contador fim 100000)
forkIO (oper (-) contador fim 100000)
waitThreads fim
v <- atomically (readTVar contador)
putStr (show v)
waitThreads :: MVar Int -> IO ()
...

Contador transacional ERRADO


oper :: (Int->Int->Int) -> TVar Int ->
MVar Int -> Int -> IO()
oper op cont fim 0
= do f <- takeMVar fim
putMVar fim (f-1)
oper op cont fim num
= do v <- atomically (readTVar cont)
atomically (writeTVar cont (op v 1))
oper op cont fim (num-1)

Leitura e escrita precisam estar na mesma transao!!!

3/14/13

Tentando de novo: funo retry

Contador transacional CORRIGIDO


oper :: (Int->Int->Int) -> TVar Int ->
MVar Int -> Int -> IO()
oper op cont fim 0
= do f <- takeMVar fim
putMVar fim (f-1)
oper op cont fim num
= do atomically (do v <- readTVar cont
writeTVar cont (op v 1)
)
oper op cont fim (num-1)

Tenta executar uma transao novamente, do


comeo
Do comeo

Usada quando uma condio necessria no


sa<sfeita
Bloqueia a transao temporariamente
Tenta de novo quando os TVars envolvidos mudam

Um exemplo bancrio
import ...
waitThreads :: MVar Int -> IO()
...
main::IO()
main = do
bal <- atomically (newTVar 0.0)
invest <- atomically (newTVar 0.0)
fim <- newMVar 2
forkIO (makeInvestment bal invest fim)
forkIO (incrementBalance bal fim)
waitThreads fim
e <- atomically (readTVar bal)
f <- atomically (readTVar invest)
putStr ("Balance: " ++ show e ++ "\n")
putStr ("Investment: " ++ show f ++ "\n")
return ()

Um exemplo bancrio (cont2.)


makeInvestment :: TVar Float -> TVar Float -> MVar Int ->
IO ()
makeInvestment acc inv fim =
do
atomically(
do
a <- readTVar acc
b <- readTVar inv
if a < 1000 then retry --condio no satisfeita
else do
writeTVar inv 1000
c <- readTVar acc
writeTVar acc (c - 1000)
)
f <- takeMVar fim
putMVar fim (f-1)

Um exemplo bancrio (cont.)


incrementBalance :: TVar Float -> MVar Int -> IO ()
incrementBalance tvb fim = do
atomically(ib tvb)
f <- takeMVar fim
putMVar fim (f-1)
ib :: TVar Float -> STM ()
ib tvb = do
y <- readTVar tvb
writeTVar tvb (y + 1)
if y < 10000 then (ib tvb)
else (return ())
...

Rodando o exemplo bancrio


Sada:
Balance: 9001.0
Investment: 1000.0
Esperada?

Checagem no if de ib feita com o valor an<go de


tvb
E ib roda sempre na mesma transao
Em que isso afeta makeInvestment?

3/14/13

Um outro exemplo bancrio


import ...

main::IO()
main = do
bal <- atomically (newTVar 0.0)
invest <- atomically (newTVar 0.0)
forkIO (incrementBalance bal)
-- Sem waitThreads. Por qu?
makeInvestment bal invest
e <- atomically (readTVar bal)
f <- atomically (readTVar invest)
putStr ("Balance: " ++ show e ++ "\n")
putStr ("Investment: " ++ show f ++ "\n")
return ()

Um outro exemplo bancrio (cont.)


incrementBalance :: TVar Float -> IO ()
incrementBalance tvb = do
atomically(ib tvb)
incrementBalance tvb
-- ib uma transao menor
ib :: TVar Float -> STM ()
ib tvb = do
y <- readTVar tvb
writeTVar tvb (y + 1)

Um outro exemplo bancrio (cont2.)


makeInvestment :: TVar Float -> TVar Float -> IO ()
makeInvestment acc inv =
do
atomically(
do
a <- readTVar acc
b <- readTVar inv
if a < 1000 then retry
else do
writeTVar inv 1000
c <- readTVar acc
writeTVar acc (c - 1000)
)

Sada possvel:
Balance: 23382.0
Investment: 1000.0

Vous aimerez peut-être aussi