Frage

Dies ist nur ein hypothetisches Szenario meiner Frage zu illustrieren. Nehmen wir an, daß es zwei Threads und einer TVar zwischen ihnen geteilt. In einem Thread gibt es eine atomar Block, der die TVar liest und 10s in Anspruch nimmt. In einem anderen Thread ist ein atomar dass ändert jeden zweiten Block der TVar. Wird die erste atomar kompletten Block jemals? Sicherlich wird es nur immer an den Anfang zurück, da das Protokoll fortwährend in einem inkonsistenten Zustand ist?

War es hilfreich?

Lösung

Wie schon andere gesagt haben: in der Theorie gibt es keine Garantie für Fortschritt. In der Praxis gibt es auch keine Garantie für den Erfolg:

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"

Das oben nie sagt: "Fertig mit langen STM" in meinen Tests.

Natürlich, wenn Sie denken, die Berechnung noch gültig / relevant sein wird, dann würden Sie wollen entweder

  1. Lassen Sie das Atom-Block, führen teure Berechnung, geben Sie die atomaren Block / bestätigen Annahmen gültig sind / und den Wert aktualisieren. Potenziell gefährlich, aber nicht mehr, als die meisten Sicherungsstrategien.
  2. Memoize die Ergebnisse im atomaren Block, so dass das nach wie vor gültige Ergebnis werden nicht mehr als eine billige Lookup nach einem erneuten Versuch.

Andere Tipps

STM verhindert Deadlocks, aber es ist zu Hunger nach wie vor anfällig. Es ist möglich, in einem pathologischen Fall für die 1s-Atom Aktion immer die Ressource zu erwerben.

die Änderungen dieses Geschehens sind jedoch sehr selten - ich glaube nicht, dass ich jemals in der Praxis gesehen habe

.

Für die Semantik finden Sie unter Composable Speichertransaktionen , Abschnitt 6.5 "Progress". STM in Haskell garantiert nur, dass eine laufende Transaktion (das heißt kein Deadlock) erfolgreich begehen wird, aber im schlimmsten Fall eine unendliche Transaktion wird andere blockieren.

Nein, wäre es gut funktionieren. Genau wie die beiden Fäden würde auf interact hängt die Wiederholungslogik.

Zum Beispiel, sagen wir, Sie haben:

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

So ist der „ten“ Thread wird, bis die TVar erreicht in Wiederholungszustand sein der Wert 7, dann wird es gehen.

Beachten Sie, dass Sie nicht direkt steuern kann, wie lange diese Berechnungen nehmen innerhalb des STM Monade. Das wäre ein Nebeneffekt sein, und Nebenwirkungen sind nicht in STM Berechnungen erlaubt. Der einzige Weg, um mit der Außenseite zu kommunizieren, Welt ist über Werte durch Transaktionsspeicher übergeben.

Und das bedeutet, dass, wenn die „Staffelstab-Passing“ Logik durch Transaktionsspeicher ist korrekt, wird das Programm korrekt funktioniert unabhängig von dem genauen Betrag Zeit davon jeder teilnimmt. Das ist ein Teil der Garantie von STM.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top