gpt4 book ai didi

arrays - 对 MutableByteArray 的写入是原子的吗?

转载 作者:行者123 更新时间:2023-12-04 08:52:18 25 4
gpt4 key购买 nike

我正在使用 primitive package而且我想确保来自一个线程的写入(特别是比单词宽的类型)不能被视为来自另一个线程的垃圾。这有时被称为“撕裂”。

最佳答案

我猜这是未定义的行为,并且在任何情况下多字写入都不是原子的,正如这个快速而肮脏的程序所证明的那样:

{-# LANGUAGE BangPatterns #-}
{-# LANGUAGE FlexibleInstances #-}
{-# LANGUAGE MagicHash #-}
{-# LANGUAGE UnboxedTuples #-}
module Main where
import Data.Primitive.Types
import Data.Primitive.ByteArray
import Control.Concurrent
import Control.Concurrent.STM
import Control.Applicative
import Control.Monad
import GHC.Prim
main = do
arr <- newByteArray 16 -- on 64-bit, this is enough for two Ints (8 each)
inp <- newTVarIO (0::Int)
o1 <- newEmptyTMVarIO
o2 <- newEmptyTMVarIO
let writer last = do
val <- atomically $ do
x <- readTVar inp
x <$ check (x > last)
let v' = (val,val+1)
writeByteArray arr 0 v'
atomically $ putTMVar o1 ()
writer val
reader last = do
val <- atomically $ do
x <- readTVar inp
x <$ check (x > last)
rVal <- readByteArray arr 0 :: IO (Int,Int)
let v1 = (val,val+1)
v0 = (val-1,val)
when (not $ rVal `elem` [v0,v1,(0,0)]) $ error $ show (val, "got:", rVal)
atomically $ putTMVar o2 ()
reader val
let control :: Int -> IO ()
control !n = do
atomically $ writeTVar inp n
mapM_ (atomically . takeTMVar) [o1,o2]
when (n<100000) $ control (n+1)
forkIO $ writer 0
forkIO $ reader 0
control 1
print "done!"

instance Prim (Int,Int) where
sizeOf# _ = 2# *# (sizeOf# (undefined :: Int))
alignment# _ = alignment# ( undefined :: Int)
readByteArray# arr n s = case readByteArray# arr (2# *# n) s of
(#s',i1 #) -> case readByteArray# arr ((2# *# n) +# 1#) s of
(#s'2,i2 #) -> (#s'2,(i1,i2)#)
writeByteArray# arr n (i1,i2) s = case writeByteArray# arr (2# *# n) i1 s of
s' -> writeByteArray# arr ((2# *# n) +# 1#) i2 s'

使用 ghc-7.6.3 构建此程序, -O2 -threaded -rtsopts ,在 7 次处决中, -N3我得到了以下结果:
foo: (4,"got:",(3,5))
foo: (59037,"got:",(59036,59038))
foo: "done!"
foo: (92936,"got:",(92936,92936))
foo: (399,"got:",(398,400))
foo: (7196,"got:",(7195,7197))
foo: (11950,"got:",(11950,11950))

只要 CPU 架构的内存模型能够保证,单个机器字的读/写可能是原子的。

对此演示的一个反对意见是 (Int,Int) 的 Prim 实例是假的。它有点像。但是,考虑到可用的原语,我看不出如何为多字类型实现更好的东西。

您需要使用其他一些同步方法来确保多字写入是原子的。一种简单的方法是将数组保存在 MVar 中。 .或者我的 kickchan包会有所帮助(至少鼓舞人心,如果它不能解决您的用例)。

关于arrays - 对 MutableByteArray 的写入是原子的吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/22264978/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com