Đây chỉ là một kịch bản giả định để minh họa cho câu hỏi của tôi. Giả sử rằng có hai luồng và một TVar được chia sẻ giữa chúng. Trong một chủ đề có một khối nguyên tử đọc TVar và mất 10 giây để hoàn thành. Trong một chủ đề khác là một khối nguyên tử mà sửa đổi TVar mỗi giây. Khối nguyên tử đầu tiên có hoàn thành không? Chắc chắn nó sẽ chỉ tiếp tục quay trở lại ban đầu, bởi vì nhật ký là vĩnh viễn trong một trạng thái không nhất quán?STM monad problem
Trả lời
Như những người khác đã nói: về lý thuyết không có đảm bảo về tiến độ. Trong thực tế, cũng không đảm bảo tiến độ:
import Control.Monad -- not needed, but cleans some things up
import Control.Monad.STM
import Control.Concurrent.STM
import Control.Concurrent
import GHC.Conc
import System.IO
main = do
tv <- newTVarIO 0
forkIO (f tv)
g tv
f :: TVar Int -> IO()
f tv = forever $ do
atomically $ do
n <- readTVar tv
writeTVar tv (n + 1)
unsafeIOToSTM (threadDelay 100000)
putStr "."
hFlush stdout
g :: TVar Int -> IO()
g tv = forever $ do
atomically $ do
n <- readTVar tv
writeTVar tv (n + 1)
unsafeIOToSTM (threadDelay 1000000)
putStrLn "Done with long STM"
Ở trên không bao giờ nói "Đã xong với STM dài" trong thử nghiệm của tôi.
Rõ ràng nếu bạn nghĩ việc tính toán vẫn sẽ có giá trị/thích hợp sau đó bạn sẽ muốn một trong hai
- Rời khỏi khối nguyên tử, thực hiện tính toán đắt tiền, nhập khối nguyên tử/xác nhận giả định là hợp lệ/và cập nhật giá trị. Có tiềm năng nguy hiểm, nhưng không nhiều hơn so với hầu hết các chiến lược khóa.
- Ghi nhớ kết quả trong khối nguyên tử để kết quả vẫn hợp lệ sẽ không quá một tra cứu giá rẻ sau khi thử lại.
Không, nó sẽ hoạt động tốt. Chính xác cách hai luồng sẽ tương tác phụ thuộc vào logic thử lại.
Ví dụ, giả sử bạn có:
ten tv = do
n <- readTVar tv
when (n < 7) retry
writeTVar tv 0
-- do something that takes about 10 seconds
one tv = do
modifyTVar tv (+1)
-- do something that takes about 1 second
Vì vậy, các "ten
" chủ đề sẽ được ở trạng thái thử lại cho đến khi đạt TVar giá trị 7, sau đó nó sẽ được tiến hành.
Lưu ý rằng bạn không thể kiểm soát trực tiếp thời gian các tính toán này sẽ mất bên trong đơn vị STM. Đó sẽ là một tác dụng phụ, và tác dụng phụ không phải là được phép trong các phép tính STM. Cách duy nhất để giao tiếp với thế giới bên ngoài là thông qua các giá trị được truyền qua bộ nhớ giao dịch. Và điều đó có nghĩa là nếu logic "đi qua baton" qua bộ nhớ giao dịch là đúng, chương trình sẽ hoạt động chính xác độc lập với số tiền chính xác của mọi thời gian cần thiết. Đó là một phần của sự bảo đảm của STM.
Tôi thực sự đang nghĩ đến trường hợp xấu nhất. Hãy quên retrys một lúc và chỉ nghĩ về hai luồng, và xem xét việc thực thi STM 'mười'. Nó đọc TVar và cam kết giá trị đó cho nhật ký. Trong khi đó, các chủ đề khác thay đổi rằng TVar luôn trong quá trình thực hiện 'mười'.Vì vậy, khi kết thúc việc thực hiện 'mười', giá trị trong TV thực không giống như giá trị ban đầu được đọc trong 'mười', buộc 'mười' để khởi tạo lại nhật ký và thực thi lại mọi lúc. – Alex
Như Yitz đã nói, nó phụ thuộc. Có, nó có thể xây dựng một tình huống mà một giao dịch không bao giờ có thể hoàn thành. Hoặc chính thức hơn, STM không đảm bảo tiến độ. –
STM ngăn chặn bế tắc, nhưng vẫn dễ bị đói. Có thể trong trường hợp bệnh lý cho hành động nguyên tử 1s để luôn thu hút tài nguyên.
Tuy nhiên, những thay đổi của sự cố này rất hiếm - tôi không tin rằng mình từng thấy nó trong thực tế.
Để biết ngữ nghĩa, hãy xem Composable Memory Transactions, phần 6.5 "Tiến trình". STM trong Haskell chỉ đảm bảo rằng một giao dịch đang chạy sẽ thực hiện thành công (nghĩa là không có bế tắc), nhưng trong trường hợp xấu nhất, một giao dịch vô hạn sẽ chặn các giao dịch khác.
Cảm ơn bạn đã tham khảo. – Alex
STM không nhất thiết không bị chặn. –
- 1. Kết quả của monad bên trong biến áp monad
- 2. Enumerable.Except Problem
- 3. INotifyPropertyChanged problem
- 4. Thư viện băm STM cho C (glib?)
- 5. Hiệu suất/khóa kém với STM
- 6. Partiality Monad Transformer
- 7. Haskell: FIFO monad
- 8. Haskell Monad Chức năng
- 9. Đằng Parsec Monad
- 10. help with reader monad
- 11. Ví dụ Monoid Monad
- 12. jqGrid overlay problem
- 13. .net DrawString/StringFormat problem
- 14. XmlTextWriter serialization problem
- 15. Trailing slashes problem
- 16. Neo4j OutOfMemory problem
- 17. rerenderEvents/refetchEvents problem
- 18. CalendarExtender Positioning Problem
- 19. UpdatePanel, Repeater, DataBinding Problem
- 20. Regex C# problem
- 21. JSplitPane SetDividerLocation Problem
- 22. Spotify puzzle problem
- 23. WPF CommandParameter Binding Problem
- 24. LINQ options.loadwith problem
- 25. mysql join problem
- 26. Sprockets require_directory problem
- 27. Jquery animate bottom problem
- 28. Android ActivityGroup Menu Problem
- 29. C# string manipulation problem
- 30. Process.Start Permissions Problem
Ví dụ tuyệt vời. Tôi muốn thử nghiệm với một cái gì đó như thế này, nhưng tôi đã không nhận thức được chức năng 'unsafeIOToSTM'! – Alex