ich einige Experimente mit Nebenläufigkeit und Speichern Sichtbarkeit zu tun und lief in dieses seltsame Verhalten (siehe Kommentare inline):Verästelter IOREF Leserfunktion scheint Haupt-Thread zum Stillstand
module Main
where
import Data.IORef
import Control.Concurrent
import System.CPUTime
import System.IO
main = do
hSetBuffering stdout NoBuffering
r <- newIORef False
putStrLn "forking..." -- PRINTED
forkIO $ f r
threadDelay 1000000
putStrLn "writeIORef" -- NEVER PRINTED
writeIORef r True
threadDelay maxBound
f :: IORef Bool -> IO()
f r = readIORef r >>= \b-> if b then print "NEVER PRINTED" else f r
ich vielleicht erwartet hatte die writeIORef
nicht zu sein sichtbar für den Unterthread, aber nicht für den Hauptthread, um (scheinbar) einfach anzuhalten.
auf ghc Zusammengestellt 7.8.3
cabal exec ghc -- --make -fforce-recomp -O2 -threaded visibility.hs
und laufen mit
./visibility +RTS -N
Was hier geschieht?
EDIT: Also meine Maschine hat zwei echte Kerne und zwei Hyperthreading-Kerne, so mit +RTS -N
GHC sieht 4 Möglichkeiten. Per Gabriel Gonzalez Antwort habe ich versucht, die folgende zu sehen, ob vielleicht wurde der Scheduler auf dem gleichen physischen Prozessor beiden Fäden setzen:
module Main
where
import Data.IORef
import Control.Concurrent
import GHC.Conc(threadCapability,myThreadId,forkOn)
main = do
r <- newIORef False
putStrLn "going..."
(cap,_) <- threadCapability =<< myThreadId
forkOn (cap+1) $ f r -- TRIED cap+1, +2, +3....
threadDelay 1000000
putStrLn "writeIORef" -- BUT THIS STILL NEVER RUNS
writeIORef r True
threadDelay maxBound
f :: IORef Bool -> IO()
f r = readIORef r >>= \b-> if b then print "A" else f r
Genau. Eine Lösung besteht darin, die "Ausbeute" zu verwenden, um Blöcke ohne Zuweisungen oder andere solche Punkte aufzuteilen. Also für das hektische Warten auf die Frage hätten wir '... sonst gib >> f r'. Offensichtlich sind Busy Loops generell eine schlechte Idee. Eine Alternative besteht darin, "MVar" und "takeMVar" zur Signalisierung zu verwenden. –
Sorry, vielleicht bin ich dicht ... Warum sollte ich den gegabelten Thread brauchen, um die Kontrolle zurück zum Haupt-Thread zu geben, damit 'putStrLn" writeIORef "' läuft? Ich laufe mit '+ RTS -N ', kompiliert mit' -hreaded'; sollen die beiden Threads nicht gleichzeitig laufen? – jberryman
Bitte sehen Sie meine Bearbeitung, auch – jberryman