यह सही है। पहले मामले में आप क्या कर रहे हैं rand_r
की थ्रेड-सुरक्षा प्रकृति को छोड़कर। कई गैर-थ्रेड-सुरक्षित कार्यों के साथ, उस स्थिति में कॉल के बीच लगातार स्थिति संग्रहीत होती है (जैसे यादृच्छिक बीज)।
थ्रेड-सुरक्षित संस्करण के साथ, आप वास्तव में डेटा के थ्रेड-विशिष्ट टुकड़े (seed1
और seed2
) प्रदान करते हैं ताकि यह सुनिश्चित किया जा सके कि राज्य धागे के बीच साझा नहीं किया गया है।
ध्यान रखें कि यह संख्याओं को वास्तव में यादृच्छिक नहीं बनाता है, यह सिर्फ एक दूसरे से स्वतंत्र अनुक्रम बनाता है। यदि आप उन्हें एक ही बीज के साथ शुरू करते हैं, तो आप शायद दोनों धागे में एक ही अनुक्रम प्राप्त करेंगे।
उदाहरण के तौर पर, मान लीजिए कि आपको एक यादृच्छिक अनुक्रम 2, 3, 5, 7, 11, 13, 17 प्राप्त होता है जो 0 के आरंभिक बीज को दिया जाता है। साझा बीज के साथ, rand_r
पर दो अलग-अलग धागे से वैकल्पिक कॉल इस कारण:
thread 1 thread 2
<--- 2
3 --->
<--- 5
7 --->
<--- 11
13 --->
<--- 17
और उस सबसे अच्छा मामला है - आप वास्तव में लग सकता है कि साझा राज्य दूषित हो जाता है, क्योंकि यह के बारे में अपडेट परमाणु नहीं हो सकता।
thread 1 thread 2
<--- 2a
2b --->
<--- 3a
3b --->
<--- 5a
5b --->
::
कुछ धागे की सुरक्षित कॉल इस तरह धागे की विशिष्ट राज्य प्रदान करने के लिए आप की आवश्यकता होती है, दूसरों:
गैर साझा राज्य (
a
और
b
यादृच्छिक संख्या के दो अलग-अलग स्रोतों का प्रतिनिधित्व करने के साथ) के साथ
कवर के तहत थ्रेड-विशिष्ट डेटा बना सकते हैं (थ्रेड आईडी या इसी तरह की जानकारी का उपयोग करके) ताकि आपको इसके बारे में चिंता करने की आवश्यकता न हो, और आप थ्रेडेड और गैर-थ्रेडेड वातावरण में बिल्कुल उसी स्रोत कोड का उपयोग कर सकें। मैं बाद वाले को पसंद करता हूं, क्योंकि यह मेरी जिंदगी को आसान बनाता है।
संपादित प्रश्न के लिए अतिरिक्त सामान:
> If in thread 1, I need a random number between 1 to n, should I do '(rand_r(&seed1) % (n-1)) + 1', or there is other common way of doing this?
मान लिया जाये कि आप 1
और n
समावेशी के बीच कोई मान चाहते हैं, (rand_r(&seed1) % n) + 1
का उपयोग करें। पहला बिट आपको 0
से n-1
समेत एक मान देता है, फिर आप वांछित सीमा प्राप्त करने के लिए 1 जोड़ते हैं।
> Is it right or normal if the memory for the seed is dynamically allocated?
बीज के रूप में आप इसे प्रयोग कर रहे हैं जब तक लगातार हो गया है। आप इसे गतिशील रूप से थ्रेड में आवंटित कर सकते हैं लेकिन आप इसे थ्रेड के शीर्ष-स्तरीय फ़ंक्शन में भी घोषित कर सकते हैं। उन दोनों मामलों में, आपको किसी भी तरह के निचले स्तर पर पते को संवाद करने की आवश्यकता होगी (जब तक कि आपका धागा केवल एक ऐसा कार्य न हो जो असंभव है)।
आप या तो इसे फ़ंक्शन कॉल के माध्यम से पास कर सकते हैं या किसी वैश्विक सरणी को सेट कर सकते हैं जहां निचले स्तर सही बीज पते की खोज कर सकते हैं।
वैकल्पिक रूप से, चूंकि आपको वैश्विक सरणी की आवश्यकता है, इसलिए आपके पास बीज पते की बजाय बीज की वैश्विक सरणी हो सकती है, जो निम्न स्तर उनके बीज को खोजने के लिए उपयोग कर सकते हैं।
आप शायद (वैश्विक सरणी का उपयोग करने के दोनों मामलों में) की एक महत्वपूर्ण संरचना है जिसमें थ्रेड आईडी को एक कुंजी और उपयोग करने के लिए बीज शामिल है। इसके बाद आपको अपने अपनेrand()
दिनचर्या लिखनी होगी जो सही बीज स्थित है और इसके साथ rand_r()
कहा जाता है।
यह यही कारण है कि मैं लाइब्रेरी दिनचर्या पसंद करता हूं जो थ्रेड-विशिष्ट डेटा के साथ कवर के तहत ऐसा करता है।
धन्यवाद !! तो सबसे अच्छा तरीका अलग-अलग धागे के लिए अलग-अलग शुरुआती मूल्यों के साथ हमेशा अलग-अलग बीज का उपयोग कर रहा है, है ना? – derrdji
मैं आमतौर पर कहूंगा, हाँ। लेकिन ऐसी कुछ स्थितियां हैं जहां आप _want_ साझा स्थिति (मेरे उत्तर में पहला आरेख) कर सकते हैं, इस मामले में आप _same_ राज्य के साथ 'rand_r' को कॉल करके भ्रष्टाचार की संभावना से बच सकते हैं लेकिन म्यूटेक्स द्वारा संरक्षित हैं। एक चीज जिसे आप नहीं करना चाहते हैं, दोनों अनुक्रमों को उसी बीज के साथ शुरू करना है क्योंकि अनुक्रम तब समान होंगे। – paxdiablo
हाँ, धन्यवाद !! मैं बस यह पूछने वाला था कि क्या मैं एक साझा कर सकता हूं और mutex लॉक के साथ rand_r कॉल को सुरक्षित रख सकता हूं। – derrdji