Может ли одна транзакция обновить два разных TVar
s в атомном режиме? то есть я могу составлять структуры данных из партий TVar
с для уменьшения конкуренции? Если да, можете ли вы привести пример?Haskell: Обновление двух или более ТВАР атомарно. Возможное?
ответ
Может ли одна транзакция обновить два разных телевизора в атомном режиме?
Да, вы можете обновлять несколько ТВАР атомарно за одну транзакцию. Это всего лишь точка STM. Было бы не очень полезно, если бы вы не смогли.
Могу ли я создавать структуры данных из множества ТВАР, чтобы уменьшить конфликт? Если да, можете ли вы привести пример?
Вот (несколько глупый) пример хранения ТВАР в структуре данных. Он имитирует кучу случайных параллельных транзакций между счетами в банке, где каждая учетная запись всего лишь TVar Integer
. Учетные TVars хранятся на карте из идентификаторов учетных записей, которые сами хранятся в TVar, так что новые учетные записи могут создаваться «на лету».
import Control.Concurrent
import Control.Concurrent.MVar
import Control.Concurrent.STM
import Control.Monad
import System.Random
import qualified Data.Map as Map
type AccountId = Int
type Account = TVar Dollars
type Dollars = Integer
type Bank = TVar (Map.Map AccountId Account)
numberOfAccounts = 20
threads = 100
transactionsPerThread = 100
maxAmount = 1000
-- Get account by ID, create new empty account if it didn't exist
getAccount :: Bank -> AccountId -> STM Account
getAccount bank accountId = do
accounts <- readTVar bank
case Map.lookup accountId accounts of
Just account -> return account
Nothing -> do
account <- newTVar 0
writeTVar bank $ Map.insert accountId account accounts
return account
-- Transfer amount between two accounts (accounts can go negative)
transfer :: Dollars -> Account -> Account -> STM()
transfer amount from to = when (from /= to) $ do
balanceFrom <- readTVar from
balanceTo <- readTVar to
writeTVar from $! balanceFrom - amount
writeTVar to $! balanceTo + amount
randomTransaction :: Bank -> IO()
randomTransaction bank = do
-- Make a random transaction
fromId <- randomRIO (1, numberOfAccounts)
toId <- randomRIO (1, numberOfAccounts)
amount <- randomRIO (1, maxAmount)
-- Perform it atomically
atomically $ do
from <- getAccount bank fromId
to <- getAccount bank toId
transfer amount from to
main = do
bank <- newTVarIO Map.empty
-- Start some worker threads to each do a number of random transactions
workers <- replicateM threads $ do
done <- newEmptyMVar
forkIO $ do
replicateM_ transactionsPerThread $ randomTransaction bank
putMVar done()
return done
-- Wait for worker threads to finish
mapM_ takeMVar workers
-- Print list of accounts and total bank balance (which should be zero)
summary <- atomically $ do
accounts <- readTVar bank
forM (Map.assocs accounts) $ \(accountId, account) -> do
balance <- readTVar account
return (accountId, balance)
mapM_ print summary
putStrLn "----------------"
putStrLn $ "TOTAL BALANCE: " ++ show (sum $ map snd summary)
Это должно напечатать полный баланс нуля в конце, если во время передач не было условий гонки.
Сделка полностью атомная; если он изменяет несколько TVar
с, оба изменения будут происходить вместе, атомарно, изолированно. Все, что выполняется в одном блоке atomically
, представляет собой единую транзакцию. Например:
swap :: (Num a) => TVar a -> TVar a -> STM()
swap v1 v2 = do
a <- readTVar v1
b <- readTVar v2
writeTVar v1 b
writeTVar v2 a
Здесь swap a b
будет атомарно поменять два TVar
с. Таким образом, одно из основных преимуществ STM заключается в том, что атомарные транзакции составляют.
- 1. Обновление более чем одной строки атомарно
- 2. Обновление двух или более таблиц при доступе
- 3. атомарно обновление нескольких документов
- 4. Запись двух переменных атомарно, если условие
- 5. обновление двух или более значений в столбце в sql
- 6. слияние двух или более ревизий
- 7. Геокодирование двух или более адресов
- 8. Туннелирование двух или более объектов
- 9. Группировка двух или более потоков
- 10. Объединение двух или более SCNGeometries
- 11. слияние двух или более симуляций
- 12. Сочетание двух или более абзацев
- 13. writeToFile: атомарно: что означает атомарно?
- 14. Объедините два или более сервера для потока файла. Возможное?
- 15. Что действительно более показательно? Haskell или OCaml
- 16. Обновление записей Haskell
- 17. STM и атомарно: почему семантика этих двух программ отличается?
- 18. Возврат двух или более значений из функции
- 19. Does Dispatcher.BeginInvoke() работает атомарно?
- 20. Пакетное обновление базы данных Access (DDL). Возможное?
- 21. Обновление только части поставщика данных. Возможное?
- 22. Cuda выполняет операции атомарно
- 23. Haskell более сложный предикат
- 24. Прочитать неатомную переменную атомарно?
- 25. Редактирование/обновление графиков в Haskell
- 26. Обновление элементов списка, Haskell
- 27. одновременно запускают двух или более дизайнеров
- 28. нг-повтора на двух (или более) строк
- 29. Сравнение двух или более столбцов в SQL
- 30. Regex - Обнаружение двух или более последовательных символов
Хороший ответ. У меня есть один вопрос. Может ли блок 'atomically' быть перемещен из' randomTransaction' в 'transfer'? Я имею в виду удаление «атомарно» из «randomTransaction» и обертывание всего тела «переноса» с помощью «атомарно». –