2010-06-13 15 views
13

यह मेरे प्रश्न को स्पष्ट करने के लिए सिर्फ एक काल्पनिक परिदृश्य है। मान लीजिए कि उनके बीच दो धागे और एक टीवीर साझा किया गया है। एक धागे में एक परमाणु रूप से ब्लॉक होता है जो टीवीर को पढ़ता है और पूरा करने के लिए 10s लेता है। एक और धागे में एक परमाणु रूप से ब्लॉक होता है जो हर सेकेंड में टीवीर को संशोधित करता है। क्या पहले परमाणु रूप से ब्लॉक कभी पूरा हो जाएगा? निश्चित रूप से यह केवल शुरुआत में वापस जा रहा है, क्योंकि लॉग एक असंगत स्थिति में हमेशा के लिए है?एसटीएम मोनड समस्या

उत्तर

12

के रूप में अन्य लोगों ने कहा: सिद्धांत रूप में प्रगति की कोई गारंटी नहीं है। व्यवहार में वहाँ भी प्रगति की कोई गारंटी नहीं:

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" 

ऊपर कभी नहीं कहते हैं मेरी परीक्षणों में "लंबे समय एसटीएम का काम हो गया"।

जाहिर है अगर आपको लगता है गणना अभी भी मान्य होने जा रहा है/उचित तो आप या तो

  1. परमाणु ब्लॉक छोड़ दो चाहेगा, महंगा गणना करते हैं, परमाणु ब्लॉक में प्रवेश/की पुष्टि मान्यताओं मान्य हैं/और मूल्य अपडेट करें। संभावित रूप से खतरनाक, लेकिन अधिकतर लॉकिंग रणनीतियों से कहीं ज्यादा नहीं।
  2. परमाणु ब्लॉक में परिणामों को याद रखें ताकि फिर भी वैध परिणाम एक पुनः प्रयास के बाद सस्ते लुकअप से अधिक न हो।
+2

उत्कृष्ट उदाहरण। मैं इस तरह से कुछ परीक्षण करना चाहता था, लेकिन मुझे 'unsafeIOToSTM' समारोह से अवगत नहीं था! – Alex

2

नहीं, यह ठीक काम करेगा। वास्तव में दो धागे कैसे बातचीत करेंगे पुन: प्रयास तर्क पर निर्भर करता है।

उदाहरण के लिए, मान लीजिए कि आप डालते हैं:

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 

तो "ten" धागा पुन: प्रयास राज्य में हो जाएगा जब तक Tvar मूल्य 7, तो यह आगे बढ़ेगा तक पहुँचता है।

ध्यान दें कि आप सीधे नियंत्रित नहीं कर सकते कि कब तक इन गणनाओं एसटीएम इकाई के अंदर ले जाएगा। यह एक साइड इफेक्ट होगा, और साइड इफेक्ट्स एसटीएम गणनाओं में अनुमत नहीं हैं। बाहर दुनिया के साथ संवाद करने का एकमात्र तरीका लेनदेन संबंधी स्मृति के माध्यम से पारित मूल्यों के माध्यम से है।

और इसका मतलब है कि अगर "लाठी गुजर" व्यवहार स्मृति के माध्यम से तर्क सही है, कार्यक्रम सही ढंग से स्वतंत्र रूप से सटीक राशि समय की इसका कोई भी भाग लेता है के लिए काम करेंगे। यह एसटीएम की गारंटी का हिस्सा है।

+0

मैं वास्तव में एक सबसे खराब स्थिति के बारे में सोच रहा हूँ। आइए एक पल के लिए पुनः प्रयास करें और बस दो धागे के बारे में सोचें, और एसटीएम 'दस' के निष्पादन पर विचार करें। यह टीवीर पढ़ता है, और लॉग के मूल्य को मानता है। इस बीच, अन्य थ्रेड हमेशा 'दस' के निष्पादन के दौरान टीवीर बदलता है।इसलिए, 'दस' के निष्पादन के अंत में, वास्तविक टीवीर में मूल्य 'दस' में शुरू होने वाले मान के समान नहीं है, जो 'दस' को लॉग-फिर से शुरू करने और हर बार पुन: निष्पादित करने के लिए मजबूर करता है। – Alex

+1

जैसा कि यित्ज़ ने कहा, यह निर्भर करता है। हां, ऐसी स्थिति बनाना संभव है जहां लेनदेन कभी पूरा न हो। या अधिक औपचारिक रूप से, एसटीएम प्रगति की गारंटी नहीं देता है। –

5

एसटीएम गतिरोध से बचाता है, लेकिन अभी भी भुखमरी की चपेट में है। संसाधनों को हमेशा प्राप्त करने के लिए 1 एस परमाणु कार्रवाई के लिए एक रोगजनक मामले में यह संभव है।

बहरहाल, यह हो रहा है की परिवर्तन बहुत दुर्लभ हैं - मैं नहीं मानता कि मैंने कभी व्यवहार में देखा है।

अर्थ विज्ञान के लिए, देखें Composable Memory Transactions, खंड 6.5 "प्रगति"। हास्केल में एसटीएम केवल गारंटी देता है कि एक चल रहा लेनदेन सफलतापूर्वक प्रतिबद्ध होगा (यानी कोई डेडलॉक नहीं), लेकिन सबसे बुरे मामले में एक अनंत लेनदेन दूसरों को अवरुद्ध करेगा।

+0

संदर्भ के लिए धन्यवाद। – Alex

+0

एसटीएम अनिवार्य रूप से गैर-अवरुद्ध नहीं हैं। –

संबंधित मुद्दे