c# - मुख्य थ्रेड का आउटपुट सी#में पहले क्यों आता है?




multithreading (7)

मैंने यह छोटा कार्यक्रम लिखा:

class Program
{
    static void Main(string[] args)
    {
        Thread t = new Thread(WriteX);
        t.Start();

        for (int i = 0; i < 1000; i++)
        {
            Console.Write("O");
        }
    }

    private static void WriteX()
    {
        for (int i = 0; i < 1000; i++)
        {
            Console.Write(".");
        }
    }
}

मैंने इसे लगभग पचास बार भाग लिया, और कंसोल पर पहला चरित्र हमेशा "ओ" था। यह मेरे लिए अजीब है, क्योंकि t धागा पहले शुरू होता है तो मुख्य जारी रहता है।

क्या इसके लिए कोई स्पष्टीकरण है?


Answers

इसे मूल रूप से धागे को शुरू करने के लिए समय की आवश्यकता होती है। आप थ्रेड कोड को उसी समय के साथ ही पहली विधि के रूप में चला रहे हैं। इसलिए ध्यान में रखना कि थ्रेड शुरू करने में कितना समय लगता है और फिर उस बिंदु पर पहुंचें जहां यह लिखा जा रहा है "।" क्या इसका कोई मतलब है?

यदि आपके पास अपने ऐप में फिर से सब कुछ शुरू करने के लिए रीसेट बटन है (बाहर निकले बिना) तो आप पाएंगे कि पहला अक्षर "।" क्योंकि धागा पहले से मौजूद होगा।


तुम कहो:

"यह मेरे लिए अजीब है, क्योंकि टी धागा पहले शुरू होता है तो मुख्य जारी रहता है।"

यह सच नहीं है। "मुख्य" चलना पहले से चल रहा है। जब t.Start(); निष्पादित किया गया है, ओएस को बताया जाता है कि चल रहे राज्य में t है। ओएस तब "जल्द ही" थ्रेड के लिए निष्पादन समय निर्धारित करेगा। थ्रेड t शुरू होने तक ओएस को इस थ्रेड के निष्पादन को रोकने के निर्देश दिए जाने के अलावा कुछ और है। दूसरे शब्दों में, जब Start रिटर्न मिलता है, तो इस बात की कोई गारंटी नहीं है कि थ्रेड पहले से ही निष्पादन शुरू कर चुका है।


मुख्य प्रक्रिया धागे को आविष्कार करने के बाद अपने अगले निर्देशों को जारी रखती है, इसमें प्रकाश प्रक्रिया के रूप में थ्रेड विधि शुरू करने में समय लगेगा।


उत्तर की तुलना में अधिक सलाह नहीं :

(कृपया ध्यान दें, कि आप जो हासिल करने की कोशिश कर रहे हैं उसके लिए मुझे कोई वास्तविक जीवन उपयोग नहीं दिखाई देता है, इसलिए मैं आपकी समस्या का एक विचार के रूप में सोचता हूं / एक अवधारणा का सबूत विस्तार से समझाया नहीं जाता है।)

यदि आप अपने धागे को नियंत्रण के लिए "दौड़" चाहते हैं, तो अपने मुख्य धागे को सिर शुरू न करें! धागे को बनाने से कुछ ओवरहेड होता है और आपका मुख्य धागा पहले से ही बनाया जाता है (क्योंकि यह आपका अन्य धागा बनाता है)। यदि आप अपने मुख्य और कार्यकर्ता धागे दोनों के लिए अधिकतर समान मौके की तलाश में हैं, तो आपको अपने थ्रेड थ्रेड को मुख्य थ्रेड में बनाने की प्रतीक्षा करनी चाहिए और मुख्य थ्रेड को अपने पृष्ठभूमि थ्रेड में दौड़ शुरू करने की प्रतीक्षा करनी चाहिए। यह synch वस्तुओं द्वारा प्राप्त किया जा सकता है।

अभ्यास में यह इस तरह दिखेगा:

आपको दो मैन्युअल रीसेट इवेंट की घोषणा करनी चाहिए जो आपके मुख्य- और पृष्ठभूमि धागे दोनों के लिए दृश्यमान हैं:

private static ManualResetEvent backgroundThreadReady = new ManualResetEvent(false);
private static ManualResetEvent startThreadRace = new ManualResetEvent(false);

फिर अपने मुख्य धागे में, आपको अपने थ्रेड को प्रारंभ करने की प्रतीक्षा करनी चाहिए:

static void Main(string[] args)
{
    Thread t = new Thread(WriteX);
    t.Start();
    backgroundThreadReady.WaitOne(); // wait for background thread to be ready

    startThreadRace.Set();           // signal your background thread to start the race
    for (int i = 0; i < 1000; i++)
    {
        Console.Write("O");
    }
}

और आपके धागे में:

    private static void WriteX()
    {
        backgroundThreadReady.Set(); // inform your main thread that this thread is ready for the race

        startThreadRace.WaitOne();   // wait 'till the main thread starts the race
        for (int i = 0; i < 1000; i++)
        {
            Console.Write(".");
        }
    }

कृपया ध्यान दें कि मैं अन्य प्रतीक्षा करने योग्य सिंक ऑब्जेक्ट्स (म्यूटेक्स, ऑटोरेसेट इवेंट, कुछ हैक के साथ एक महत्वपूर्ण सेक्शन लॉक भी इस्तेमाल कर सकता था, मैंने बस सबसे सरल, सबसे तेज़ समाधान चुना है जिसे आसानी से बढ़ाया जा सकता है)।


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

थ्रेड। स्टार्ट विधि

1) थ्रेड। स्टार्ट विधि ऑपरेटिंग सिस्टम को वर्तमान उदाहरण की स्थिति को थ्रेडस्टेट में बदलने के लिए कारण बनाता है।

2) एक बार धागा थ्रेडस्टेट में है। आश्चर्यजनक स्थिति, ऑपरेटिंग सिस्टम इसे निष्पादन के लिए शेड्यूल कर सकता है। धागा थ्रेडस्टार्ट द्वारा प्रस्तुत विधि की पहली पंक्ति पर निष्पादन शुरू होता है

संपादित करें ऐसा लगता है कि ग्राफिकल रूप में इसका प्रतिनिधित्व करने से यह और अधिक स्पष्ट और समझदार हो जाएगा। मैंने नीचे आरेख में थ्रेड निष्पादन के अनुक्रम को दिखाने की कोशिश की।


आपका कोड गैर निर्धारक है। आपके कोड में कोई थ्रेड प्राइमेटिव नहीं है जो किसी थ्रेड की प्राथमिकता को दूसरे पर या एक थ्रेड के लिए दूसरे के लिए प्रतीक्षा करने के लिए शेड्यूल करेगा।


@ डोंटॉक्सटाटा आप अपने शिक्षक के पास वापस जा सकते हैं और उसे थोड़ा सा स्कूल :)

असली दुनिया से कुछ नोट्स और चाहे आप जो देखते हैं या कहा जाए। कृपया ध्यान दें, नीचे दिए गए शब्द इस विशेष मामले के बारे में दिखाए गए सटीक क्रम में हैं।

निम्नलिखित 2 चर वही कैश लाइन पर लगभग किसी भी ज्ञात वास्तुकला के अंतर्गत रहेंगे।

private static boolean ready;  
private static int number;  

धागा समूह थ्रेड हटाने (और कई अन्य मुद्दों) के कारण Thread.exit (मुख्य धागा) से बाहर exit की गारंटी है और मेमोरी बाड़ का कारण बनने की गारंटी है। (यह एक सिंक्रनाइज़ कॉल है, और मुझे सिंक भाग को लागू करने का कोई भी तरीका नहीं दिखता है क्योंकि थ्रेड ग्रुप को भी समाप्त करना होगा क्योंकि कोई डेमॉन थ्रेड छोड़ नहीं है, आदि)।

ReaderThread धागा ReaderThread थ्रेड प्रक्रिया को जीवित रखने जा रहा है क्योंकि यह एक डेमन नहीं है! इस प्रकार ready और number एक साथ फिसल जाएगी (या एक संदर्भ स्विच होने से पहले संख्या) और इस मामले में पुन: समन्वय के लिए कोई वास्तविक कारण नहीं है कम से कम मैं एक के बारे में भी सोच नहीं सकता। आपको कुछ भी देखने के लिए वास्तव में अजीब कुछ चाहिए लेकिन 42 । फिर मैं मानता हूं कि स्थैतिक चर दोनों एक ही कैश लाइन में होंगे। मैं बस एक कैश लाइन 4 बाइट्स लंबा या एक JVM कल्पना नहीं कर सकता जो उन्हें एक सतत क्षेत्र (कैश लाइन) में असाइन नहीं करेगा।





c# multithreading