खोज…


टिप्पणियों

हास्केल में समवर्ती और समानांतर प्रोग्रामिंग के बारे में सीखने के लिए अच्छे संसाधन हैं:

`ForkIO` के साथ स्प्रेडिंग थ्रेड्स

हास्केल forkIO कई रूपों का समर्थन करता है और सबसे स्पष्ट है कि forkIO का उपयोग करके एक थ्रेड forkIO

फ़ंक्शन forkIO :: IO () -> IO ThreadId एक IO एक्शन लेता है और अपने ThreadId , इस बीच ThreadId में एक्शन चलाया जाएगा।

हम इसे पूरी तरह से ghci का उपयोग करके प्रदर्शित कर सकते हैं:

Prelude Control.Concurrent> forkIO $ (print . sum) [1..100000000]
ThreadId 290
Prelude Control.Concurrent> forkIO $ print "hi!"
"hi!"
-- some time later....
Prelude Control.Concurrent> 50000005000000

दोनों क्रियाएं पृष्ठभूमि में चलेंगी, और दूसरा अंतिम से पहले समाप्त होने की गारंटी है!

`एमवीआर` के साथ थ्रेड्स के बीच संचार

MVar a का उपयोग करते हुए थ्रेड्स के बीच जानकारी को पास करना बहुत आसान है और Control.Concurrent में इसके साथ काम करता है। MVar a :

  • newEmptyMVar :: IO (MVar a) - एक नया MVar a बनाता MVar a
  • newMVar :: a -> IO (MVar a) - दिए गए मान के साथ एक नया MVar बनाता है
  • takeMVar :: MVar a -> IO a - दिए गए MVar से मान प्राप्त करता है, या एक उपलब्ध होने तक ब्लॉक करता है
  • putMVar :: MVar a -> a -> IO () - दिए गए मूल्य को MVar में डालता है, या खाली होने तक ब्लॉक करता है

आइए एक सूत्र में 1 से 100 मिलियन तक की संख्या प्राप्त करें और परिणाम पर प्रतीक्षा करें:

import Control.Concurrent
main = do
  m <- newEmptyMVar
  forkIO $ putMVar m $ sum [1..10000000]
  print =<< takeMVar m  -- takeMVar will block 'til m is non-empty!

अधिक इनपुट के लिए प्रतीक्षा करते समय पृष्ठभूमि में उपयोगकर्ता इनपुट और योग लेने के लिए एक अधिक जटिल प्रदर्शन हो सकता है:

main2 = loop
  where 
    loop = do
        m <- newEmptyMVar
        n <- getLine
        putStrLn "Calculating. Please wait"
        -- In another thread, parse the user input and sum
        forkIO $ putMVar m $ sum [1..(read n :: Int)]
        -- In another thread, wait 'til the sum's complete then print it
        forkIO $ print =<< takeMVar m
        loop

जैसा कि पहले कहा गया है, यदि आप takeMVar कहते हैं और MVar खाली है, तो यह तब तक ब्लॉक होता है जब तक कि एक और धागा MVar में कुछ डाल नहीं MVar , जिसके परिणामस्वरूप डाइनिंग फिलॉसॉफ़र्स समस्या हो सकती है । यही बात putMVar साथ putMVar : अगर यह भरा हुआ है, तो यह खाली हो जाएगा!

निम्नलिखित कार्य करें:

concurrent ma mb = do
  a <- takeMVar ma
  b <- takeMVar mb
  putMVar ma a
  putMVar mb b

हम दो कार्यों को कुछ MVar साथ MVar

concurrent ma mb     -- new thread 1 
concurrent mb ma     -- new thread 2

क्या हो सकता है:

  1. थ्रेड 1 पढ़ता ma और ब्लॉक ma
  2. थ्रेड 2 पढ़ता है mb और इस प्रकार mb ब्लॉक करता है

अब थ्रेड 1 mb को नहीं पढ़ सकता क्योंकि थ्रेड 2 ने इसे ब्लॉक कर दिया है, और थ्रेड 2 ma को नहीं पढ़ सकता क्योंकि थ्रेड 1 ने इसे ब्लॉक कर दिया है। एक क्लासिक गतिरोध!

सॉफ्टवेयर ट्रांजैक्शनल मेमोरी के साथ परमाणु ब्लॉक

हास्केल में एक और शक्तिशाली और परिपक्व संगामिति उपकरण है सॉफ्टवेयर ट्रांजैक्शनल मेमोरी, जो कई थ्रेड्स के लिए TVar a ही चर में एक परमाणु तरीके से लिखने की अनुमति देता है।

TVar a मुख्य प्रकार है जो STM TVar a जुड़ा होता है और इसका मतलब होता है लेन-देन चर। वे MVar तरह उपयोग किए जाते हैं, लेकिन निम्नलिखित कार्यों के माध्यम से STM MVar भीतर:

atomically :: STM a -> IO a

एसटीएम क्रियाओं की एक श्रृंखला को परमाणु रूप से निष्पादित करें।

readTVar :: TVar a -> STM a

TVar का मान पढ़ें, जैसे:

value <- readTVar t

writeTVar :: TVar a -> a -> STM ()

दिए गए TVar मान लिखें।

t <- newTVar Nothing
writeTVar t (Just "Hello")

यह उदाहरण हास्केल विकी से लिया गया है:

import Control.Monad
import Control.Concurrent
import Control.Concurrent.STM
 
main = do 
  -- Initialise a new TVar
  shared <- atomically $ newTVar 0
  -- Read the value
  before <- atomRead shared
  putStrLn $ "Before: " ++ show before
  forkIO $ 25 `timesDo` (dispVar shared >> milliSleep 20)
  forkIO $ 10 `timesDo` (appV ((+) 2) shared >> milliSleep 50)
  forkIO $ 20 `timesDo` (appV pred shared >> milliSleep 25)
  milliSleep 800
  after <- atomRead shared
  putStrLn $ "After: " ++ show after
  where timesDo = replicateM_
       milliSleep = threadDelay . (*) 1000

atomRead = atomically . readTVar
dispVar x = atomRead x >>= print
appV fn x = atomically $ readTVar x >>= writeTVar x . fn


Modified text is an extract of the original Stack Overflow Documentation
के तहत लाइसेंस प्राप्त है CC BY-SA 3.0
से संबद्ध नहीं है Stack Overflow