ध्यान दें:
गो 1.5 के रूप में, GOMAXPROCS हार्डवेयर के कोर की संख्या पर सेट है: golang.org/doc/go1.5#runtime , मूल उत्तर 1.5 से नीचे।
जब आप GOMAXPROCS पर्यावरण चर को निर्दिष्ट किए बिना गो कार्यक्रम चलाते हैं, तो गो OSoutines एकल OS थ्रेड में निष्पादन के लिए निर्धारित है। हालाँकि, प्रोग्राम बनाने के लिए मल्टीथ्रेडेड दिखाई देते हैं (जो कि गोरोइटिन हैं, वे नहीं हैं?), गो शेड्यूलर को कभी-कभी निष्पादन के संदर्भ को बंद करना होगा, इसलिए प्रत्येक गोरआउट अपना काम कर सकता है।
जैसा कि मैंने कहा, जब GOMAXPROCS चर निर्दिष्ट नहीं किया जाता है, तो गो रनटाइम को केवल एक थ्रेड का उपयोग करने की अनुमति है, इसलिए निष्पादन के संदर्भों को स्विच करना असंभव है, जबकि गोरूटीन कुछ पारंपरिक काम कर रहा है, जैसे संगणना या यहां तक कि आईओ (जो सादे सी कार्यों के लिए मैप किया गया है) )। संदर्भ को तभी स्विच किया जा सकता है जब गो कंसिस्टेंसी प्राइमेटिव का उपयोग किया जाता है, उदाहरण के लिए जब आप कई मंत्रों पर स्विच करते हैं, या (यह आपका मामला है) जब आप संदर्भदाताओं को संदर्भों को स्विच करने के लिए स्पष्ट रूप से बताते हैं - यह वही है जो runtime.Gosched
है।
इसलिए, संक्षेप में, जब एक गोरेइन में निष्पादन संदर्भ Gosched
कॉल पर पहुंच जाता है , तो अनुसूचक को निर्देश को दूसरे गाउटआउट में बदलने का निर्देश दिया जाता है। आपके मामले में दो गोरोनाइट हैं, मुख्य (जो कि कार्यक्रम के 'मुख्य' धागे का प्रतिनिधित्व करता है) और अतिरिक्त, एक जिसे आपने बनाया है go say
। यदि आप Gosched
कॉल हटाते हैं, तो निष्पादन संदर्भ को पहले गोरोइन से दूसरे में स्थानांतरित नहीं किया जाएगा, इसलिए आपके लिए कोई 'दुनिया' नहीं है। जब Gosched
उपस्थित होता है, तो शेड्यूलर प्रत्येक लूप पुनरावृत्ति पर पहले गोरोइन से दूसरे और इसके विपरीत पर निष्पादन को स्थानांतरित करता है, इसलिए आपके पास 'हैलो' और 'वर्ल्ड' इंटरलेय्ड है।
FYI करें, इसे 'कोऑपरेटिव मल्टीटास्किंग' कहा जाता है: गोरोइन्ट्स को अन्य गोरआउट्स के लिए स्पष्ट रूप से नियंत्रण प्राप्त करना चाहिए। अधिकांश समकालीन OS में उपयोग किए जाने वाले दृष्टिकोण को 'प्रीमेप्टिव मल्टीटास्किंग' कहा जाता है: निष्पादन थ्रेड्स नियंत्रण हस्तांतरण के साथ संबंधित नहीं हैं; शेड्यूलर निष्पादन निष्पादन संदर्भों को पारदर्शी रूप से उनके बजाय बदल देता है। सहकारी दृष्टिकोण अक्सर 'ग्रीन थ्रेड्स' को लागू करने के लिए उपयोग किया जाता है, अर्थात्, तार्किक समवर्ती कोरआउट जो ओएस थ्रेड्स 1: 1 से मैप नहीं करते हैं - यह है कि गो रनटाइम और इसके गोरआउट्स को कैसे लागू किया जाता है।
अपडेट करें
मैंने GOMAXPROCS पर्यावरण चर का उल्लेख किया है, लेकिन यह क्या है, इसकी व्याख्या नहीं की। इसे ठीक करने का समय आ गया है।
जब यह चर एक सकारात्मक संख्या में सेट हो जाता है N
, तो गो रनटाइम N
देशी थ्रेड्स बनाने में सक्षम होगा , जिस पर सभी हरे रंग के धागे निर्धारित होंगे। मूल धागा एक प्रकार का धागा है जो ऑपरेटिंग सिस्टम (विंडोज थ्रेड्स, pthreads आदि) द्वारा बनाया गया है। इसका मतलब है कि यदि N
1 से अधिक है, तो यह संभव है कि गोरोइटिन को अलग-अलग मूल थ्रेड्स में निष्पादित करने के लिए निर्धारित किया जाएगा और, परिणामस्वरूप, समानांतर (कम से कम, आपके कंप्यूटर की क्षमताओं तक) में चलाया जाएगा: यदि आपका सिस्टम मल्टीकोर प्रोसेसर पर आधारित है, तो यह संभावना है कि ये धागे वास्तव में समानांतर होंगे; यदि आपके प्रोसेसर में सिंगल कोर है, तो ओएस थ्रेड्स में कार्यान्वित प्रीमेप्टिव मल्टीटास्किंग समानांतर निष्पादन की दृश्यता बनाएगा)।
runtime.GOMAXPROCS()
पर्यावरण चर को पूर्व-निर्धारित करने के बजाय फ़ंक्शन का उपयोग करके GOMAXPROCS चर सेट करना संभव है । करंट के बजाय अपने प्रोग्राम में कुछ इस तरह का प्रयोग करें main
:
func main() {
runtime.GOMAXPROCS(2)
go say("world")
say("hello")
}
इस मामले में आप दिलचस्प परिणाम देख सकते हैं। यह संभव है कि आपको असमान रूप से मुद्रित interleaved 'हैलो' और 'दुनिया' लाइनें मिलेंगी, जैसे
hello
hello
world
hello
world
world
...
यह हो सकता है अगर गोरोनाइट को ओएस थ्रेड्स को अलग करने के लिए निर्धारित किया जाए। यह वास्तव में है कि प्रीमेप्टिव मल्टीटास्किंग कैसे काम करता है (या मल्टीकोर सिस्टम के मामले में समानांतर प्रसंस्करण): थ्रेड्स समानांतर होते हैं, और उनका संयुक्त उत्पादन अनिश्चितकालीन होता है। BTW, आप Gosched
कॉल को छोड़ या हटा सकते हैं, ऐसा लगता है कि जब GOMAXPROCS 1 से बड़ा है तो इसका कोई प्रभाव नहीं होगा।
निम्नलिखित है जो मुझे runtime.GOMAXPROCS
कॉल के साथ कार्यक्रम के कई रनों पर मिला ।
hyperplex /tmp % go run test.go
hello
hello
hello
world
hello
world
hello
world
hyperplex /tmp % go run test.go
hello
world
hello
world
hello
world
hello
world
hello
world
hyperplex /tmp % go run test.go
hello
hello
hello
hello
hello
hyperplex /tmp % go run test.go
hello
world
hello
world
hello
world
hello
world
hello
world
देखें, कभी-कभी आउटपुट बहुत सुंदर होता है, कभी-कभी नहीं। कार्रवाई में अनिश्चिततावाद :)
एक और अपडेट
ऐसा लगता है कि गो संकलक के नए संस्करणों में गो रनटाइम गोरोइटिन को केवल संगामिति आदिम उपयोग पर नहीं बल्कि ओएस सिस्टम कॉल पर भी उपज देता है। इसका मतलब है कि निष्पादन संदर्भ को गोरों के बीच भी IO फ़ंक्शन कॉल पर स्विच किया जा सकता है। नतीजतन, हाल के गो संकलक में यह संभव है कि जब GOMAXPROCS परेशान हो या 1 पर सेट हो, तब भी अनिश्चितकालीन व्यवहार का निरीक्षण किया जा सकता है।