<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom"><channel><title>Modern C++ on kenji.blog</title><link>http://kenji.blog/hi/tags/modern-c++/</link><description>Recent content in Modern C++ on kenji.blog</description><generator>Hugo -- gohugo.io</generator><language>hi</language><copyright>kenjinote</copyright><lastBuildDate>Sat, 12 Sep 2026 08:00:00 +0900</lastBuildDate><atom:link href="http://kenji.blog/hi/tags/modern-c++/index.xml" rel="self" type="application/rss+xml"/><item><title>C++ में मल्टीथ्रेडिंग प्रोग्रामिंग और एसिंक्रोनस प्रोसेसिंग (std::async) का परिचय</title><link>http://kenji.blog/hi/p/cpp-multithreading-and-async-guide/</link><pubDate>Sat, 12 Sep 2026 08:00:00 +0900</pubDate><guid>http://kenji.blog/hi/p/cpp-multithreading-and-async-guide/</guid><description>&lt;img src="http://kenji.blog/p/cpp-multithreading-and-async-guide/img/eyecatch.jpg" alt="Featured image of post C++ में मल्टीथ्रेडिंग प्रोग्रामिंग और एसिंक्रोनस प्रोसेसिंग (std::async) का परिचय" />&lt;p>आधुनिक सॉफ्टवेयर विकास में, मल्टी-कोर CPU के प्रदर्शन को अधिकतम करने के लिए मल्टीथ्रेडिंग प्रोग्रामिंग आवश्यक है। C++11 से, C++ ने मानक लाइब्रेरी के रूप में मल्टीथ्रेडिंग और एसिंक्रोनस प्रोसेसिंग API (&lt;code>&amp;lt;thread&amp;gt;&lt;/code>, &lt;code>&amp;lt;mutex&amp;gt;&lt;/code>, &lt;code>&amp;lt;condition_variable&amp;gt;&lt;/code>, &lt;code>&amp;lt;future&amp;gt;&lt;/code>) पेश किए हैं, जिससे प्लेटफ़ॉर्म-विशिष्ट कोड (जैसे POSIX थ्रेड्स या Windows API) लिखे बिना पोर्टेबल और सुरक्षित कंकरेंट प्रोसेसिंग को लागू करना संभव हो गया है। इसके अलावा, C++14, C++17 और C++20 जैसे क्रमिक संस्करणों के साथ, &lt;code>std::scoped_lock&lt;/code> और &lt;code>std::jthread&lt;/code> जैसी अधिक सुरक्षित और उन्नत सुविधाएँ जोड़ी गई हैं।&lt;/p>
&lt;p>इस लेख में, हम C++ मल्टीथ्रेडिंग प्रोग्रामिंग के मूल सिद्धांतों से लेकर डेटा रेस (data race) को रोकने के लिए सिंक्रोनाइज़ेशन तंत्र, और आधुनिक एसिंक्रोनस प्रोसेसिंग (&lt;code>std::async&lt;/code>) के साथ-साथ थ्रेड पूल (thread pool) की अवधारणा को विस्तृत कोड उदाहरणों के साथ अच्छी तरह से समझाएंगे।&lt;/p>
&lt;hr>
&lt;h2 id="1-ककरट-परससग-क-मल-बत-और-एमडहल-क-नयम-amdahls-law">1. कंकरेंट प्रोसेसिंग की मूल बातें और एमडाहल का नियम (Amdahl&amp;rsquo;s Law)
&lt;/h2>&lt;p>मल्टीथ्रेडिंग का मुख्य उद्देश्य &amp;ldquo;प्रदर्शन में सुधार&amp;rdquo; है, लेकिन संपूर्ण प्रोग्राम को समानांतर (parallelize) नहीं किया जा सकता है। यहीं पर &lt;strong>एमडाहल का नियम (Amdahl&amp;rsquo;s Law)&lt;/strong> महत्वपूर्ण हो जाता है।&lt;/p>
&lt;p>एमडाहल का नियम एक मॉडल है जो यह अनुमान लगाता है कि प्रोग्राम के एक हिस्से को समानांतर और तेज़ करने पर संपूर्ण सिस्टम के प्रदर्शन में कितना सुधार होगा।&lt;/p>
$$ S(N) = \frac{1}{(1 - P) + \frac{P}{N}} $$
&lt;ul>
&lt;li>$S(N)$ : सैद्धांतिक अधिकतम स्पीडअप अनुपात&lt;/li>
&lt;li>$P$ : संपूर्ण प्रोग्राम का वह भाग जिसे समानांतर किया जा सकता है (0 ≤ $P$ ≤ 1)&lt;/li>
&lt;li>$N$ : प्रोसेसर (थ्रेड) की संख्या&lt;/li>
&lt;/ul>
&lt;p>यह गणितीय सूत्र जो महत्वपूर्ण तथ्य दिखाता है वह यह है कि, &amp;ldquo;चाहे आप प्रोसेसर की संख्या $N$ को कितना भी बढ़ा लें, क्रमिक भाग $(1 - P)$ जिसे समानांतर नहीं किया जा सकता, वह एक अड़चन (bottleneck) बन जाता है, और स्पीडअप की एक सीमा होती है।&amp;rdquo; उदाहरण के लिए, भले ही प्रोग्राम का $90\%$ समानांतर करने योग्य हो ($P = 0.9$), जब तक शेष $10\%$ क्रमिक प्रसंस्करण (serial processing) है, अनंत प्रोसेसर का उपयोग करने पर भी गति केवल अधिकतम $10$ गुना ($S(\infty) = 1 / 0.1$) बढ़ेगी।&lt;/p>
&lt;p>इसलिए, C++ में मल्टीथ्रेडिंग प्रोग्रामिंग करते समय, न केवल थ्रेड्स को बढ़ाना आवश्यक है, बल्कि एक ऐसे &lt;strong>डिज़ाइन की भी आवश्यकता है जो क्रमिक प्रसंस्करण भागों (जैसे लॉक कंटेंशन (lock contention) और सिंक्रोनाइज़ेशन ओवरहेड) को जितना संभव हो उतना कम कर दे&lt;/strong>।&lt;/p>
&lt;hr>
&lt;h2 id="2-थरड-क-मल-सदधत-stdthread-और-stdjthread-c20">2. थ्रेड के मूल सिद्धांत: &lt;code>std::thread&lt;/code> और &lt;code>std::jthread&lt;/code> (C++20)
&lt;/h2>&lt;h3 id="परपरक-stdthread-c11">पारंपरिक &lt;code>std::thread&lt;/code> (C++11)
&lt;/h3>&lt;p>C++11 में पेश किया गया &lt;code>std::thread&lt;/code>, एक नए थ्रेड में फ़ंक्शंस या लैम्ब्डा एक्सप्रेशन को निष्पादित करने के लिए सबसे बुनियादी क्लास है।&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt"> 1
&lt;/span>&lt;span class="lnt"> 2
&lt;/span>&lt;span class="lnt"> 3
&lt;/span>&lt;span class="lnt"> 4
&lt;/span>&lt;span class="lnt"> 5
&lt;/span>&lt;span class="lnt"> 6
&lt;/span>&lt;span class="lnt"> 7
&lt;/span>&lt;span class="lnt"> 8
&lt;/span>&lt;span class="lnt"> 9
&lt;/span>&lt;span class="lnt">10
&lt;/span>&lt;span class="lnt">11
&lt;/span>&lt;span class="lnt">12
&lt;/span>&lt;span class="lnt">13
&lt;/span>&lt;span class="lnt">14
&lt;/span>&lt;span class="lnt">15
&lt;/span>&lt;span class="lnt">16
&lt;/span>&lt;span class="lnt">17
&lt;/span>&lt;span class="lnt">18
&lt;/span>&lt;span class="lnt">19
&lt;/span>&lt;span class="lnt">20
&lt;/span>&lt;span class="lnt">21
&lt;/span>&lt;span class="lnt">22
&lt;/span>&lt;span class="lnt">23
&lt;/span>&lt;span class="lnt">24
&lt;/span>&lt;span class="lnt">25
&lt;/span>&lt;span class="lnt">26
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-cpp" data-lang="cpp">&lt;span class="line">&lt;span class="cl">&lt;span class="cp">#include&lt;/span> &lt;span class="cpf">&amp;lt;iostream&amp;gt;&lt;/span>&lt;span class="cp">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="cp">#include&lt;/span> &lt;span class="cpf">&amp;lt;thread&amp;gt;&lt;/span>&lt;span class="cp">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="cp">&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="kt">void&lt;/span> &lt;span class="nf">workerFunction&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="kt">int&lt;/span> &lt;span class="n">id&lt;/span>&lt;span class="p">)&lt;/span> &lt;span class="p">{&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">std&lt;/span>&lt;span class="o">::&lt;/span>&lt;span class="n">cout&lt;/span> &lt;span class="o">&amp;lt;&amp;lt;&lt;/span> &lt;span class="s">&amp;#34;Worker &amp;#34;&lt;/span> &lt;span class="o">&amp;lt;&amp;lt;&lt;/span> &lt;span class="n">id&lt;/span> &lt;span class="o">&amp;lt;&amp;lt;&lt;/span> &lt;span class="s">&amp;#34; is running on thread &amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="o">&amp;lt;&amp;lt;&lt;/span> &lt;span class="n">std&lt;/span>&lt;span class="o">::&lt;/span>&lt;span class="n">this_thread&lt;/span>&lt;span class="o">::&lt;/span>&lt;span class="n">get_id&lt;/span>&lt;span class="p">()&lt;/span> &lt;span class="o">&amp;lt;&amp;lt;&lt;/span> &lt;span class="n">std&lt;/span>&lt;span class="o">::&lt;/span>&lt;span class="n">endl&lt;/span>&lt;span class="p">;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="p">}&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="kt">int&lt;/span> &lt;span class="nf">main&lt;/span>&lt;span class="p">()&lt;/span> &lt;span class="p">{&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">std&lt;/span>&lt;span class="o">::&lt;/span>&lt;span class="n">cout&lt;/span> &lt;span class="o">&amp;lt;&amp;lt;&lt;/span> &lt;span class="s">&amp;#34;Main thread id: &amp;#34;&lt;/span> &lt;span class="o">&amp;lt;&amp;lt;&lt;/span> &lt;span class="n">std&lt;/span>&lt;span class="o">::&lt;/span>&lt;span class="n">this_thread&lt;/span>&lt;span class="o">::&lt;/span>&lt;span class="n">get_id&lt;/span>&lt;span class="p">()&lt;/span> &lt;span class="o">&amp;lt;&amp;lt;&lt;/span> &lt;span class="n">std&lt;/span>&lt;span class="o">::&lt;/span>&lt;span class="n">endl&lt;/span>&lt;span class="p">;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c1">// थ्रेड बनाना और निष्पादन शुरू करना
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">&lt;/span> &lt;span class="n">std&lt;/span>&lt;span class="o">::&lt;/span>&lt;span class="kr">thread&lt;/span> &lt;span class="n">t1&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">workerFunction&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="mi">1&lt;/span>&lt;span class="p">);&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c1">// लैम्ब्डा एक्सप्रेशन का उपयोग करके थ्रेड बनाना
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">&lt;/span> &lt;span class="n">std&lt;/span>&lt;span class="o">::&lt;/span>&lt;span class="kr">thread&lt;/span> &lt;span class="n">t2&lt;/span>&lt;span class="p">([](&lt;/span>&lt;span class="kt">int&lt;/span> &lt;span class="n">id&lt;/span>&lt;span class="p">)&lt;/span> &lt;span class="p">{&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">std&lt;/span>&lt;span class="o">::&lt;/span>&lt;span class="n">cout&lt;/span> &lt;span class="o">&amp;lt;&amp;lt;&lt;/span> &lt;span class="s">&amp;#34;Lambda Worker &amp;#34;&lt;/span> &lt;span class="o">&amp;lt;&amp;lt;&lt;/span> &lt;span class="n">id&lt;/span> &lt;span class="o">&amp;lt;&amp;lt;&lt;/span> &lt;span class="s">&amp;#34; is running.&amp;#34;&lt;/span> &lt;span class="o">&amp;lt;&amp;lt;&lt;/span> &lt;span class="n">std&lt;/span>&lt;span class="o">::&lt;/span>&lt;span class="n">endl&lt;/span>&lt;span class="p">;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="p">},&lt;/span> &lt;span class="mi">2&lt;/span>&lt;span class="p">);&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c1">// थ्रेड के पूरा होने की प्रतीक्षा करना (join)
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">&lt;/span> &lt;span class="n">t1&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="n">join&lt;/span>&lt;span class="p">();&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">t2&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="n">join&lt;/span>&lt;span class="p">();&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">std&lt;/span>&lt;span class="o">::&lt;/span>&lt;span class="n">cout&lt;/span> &lt;span class="o">&amp;lt;&amp;lt;&lt;/span> &lt;span class="s">&amp;#34;All threads completed.&amp;#34;&lt;/span> &lt;span class="o">&amp;lt;&amp;lt;&lt;/span> &lt;span class="n">std&lt;/span>&lt;span class="o">::&lt;/span>&lt;span class="n">endl&lt;/span>&lt;span class="p">;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">return&lt;/span> &lt;span class="mi">0&lt;/span>&lt;span class="p">;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="p">}&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>&lt;code>std::thread&lt;/code> के साथ ध्यान देने वाली बात यह है कि &lt;strong>इसके नष्ट होने से पहले &lt;code>join()&lt;/code> या &lt;code>detach()&lt;/code> को कॉल किया जाना चाहिए&lt;/strong>। यदि &lt;code>std::thread&lt;/code> का डिस्ट्रक्टर (destructor) इनमें से किसी को भी कॉल किए बिना कॉल किया जाता है, तो &lt;code>std::terminate()&lt;/code> कॉल हो जाएगा, और प्रोग्राम क्रैश हो जाएगा। अपवाद सुरक्षा (exception safety) सुनिश्चित करने के लिए, RAII पैटर्न का उपयोग करके एक कस्टम रैपर क्लास (wrapper class) बनाना आवश्यक था।&lt;/p>
&lt;h3 id="आधनक-stdjthread-c20">आधुनिक &lt;code>std::jthread&lt;/code> (C++20)
&lt;/h3>&lt;p>C++20 में, इन कमियों को दूर करते हुए &lt;code>std::jthread&lt;/code> (joining thread) पेश किया गया। &lt;code>std::jthread&lt;/code> स्वचालित रूप से अपने डिस्ट्रक्टर में &lt;code>join()&lt;/code> को कॉल करता है, जिससे अपवाद (exception) होने पर भी थ्रेड सुरक्षित रूप से पूरा होने की प्रतीक्षा कर सकता है। इसके अलावा, इसमें &lt;code>std::stop_token&lt;/code> के माध्यम से थ्रेड्स के लिए एक सहयोगी रद्दीकरण (cooperative cancellation) सुविधा भी है।&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt"> 1
&lt;/span>&lt;span class="lnt"> 2
&lt;/span>&lt;span class="lnt"> 3
&lt;/span>&lt;span class="lnt"> 4
&lt;/span>&lt;span class="lnt"> 5
&lt;/span>&lt;span class="lnt"> 6
&lt;/span>&lt;span class="lnt"> 7
&lt;/span>&lt;span class="lnt"> 8
&lt;/span>&lt;span class="lnt"> 9
&lt;/span>&lt;span class="lnt">10
&lt;/span>&lt;span class="lnt">11
&lt;/span>&lt;span class="lnt">12
&lt;/span>&lt;span class="lnt">13
&lt;/span>&lt;span class="lnt">14
&lt;/span>&lt;span class="lnt">15
&lt;/span>&lt;span class="lnt">16
&lt;/span>&lt;span class="lnt">17
&lt;/span>&lt;span class="lnt">18
&lt;/span>&lt;span class="lnt">19
&lt;/span>&lt;span class="lnt">20
&lt;/span>&lt;span class="lnt">21
&lt;/span>&lt;span class="lnt">22
&lt;/span>&lt;span class="lnt">23
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-cpp" data-lang="cpp">&lt;span class="line">&lt;span class="cl">&lt;span class="cp">#include&lt;/span> &lt;span class="cpf">&amp;lt;iostream&amp;gt;&lt;/span>&lt;span class="cp">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="cp">#include&lt;/span> &lt;span class="cpf">&amp;lt;thread&amp;gt;&lt;/span>&lt;span class="cp">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="cp">#include&lt;/span> &lt;span class="cpf">&amp;lt;chrono&amp;gt;&lt;/span>&lt;span class="cp">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="cp">&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="kt">int&lt;/span> &lt;span class="nf">main&lt;/span>&lt;span class="p">()&lt;/span> &lt;span class="p">{&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c1">// C++20: std::jthread
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">&lt;/span> &lt;span class="c1">// पहले तर्क (argument) के रूप में std::stop_token प्राप्त करके रद्दीकरण अनुरोधों का पता लगाया जा सकता है
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">&lt;/span> &lt;span class="n">std&lt;/span>&lt;span class="o">::&lt;/span>&lt;span class="n">jthread&lt;/span> &lt;span class="n">jt&lt;/span>&lt;span class="p">([](&lt;/span>&lt;span class="n">std&lt;/span>&lt;span class="o">::&lt;/span>&lt;span class="n">stop_token&lt;/span> &lt;span class="n">stoken&lt;/span>&lt;span class="p">)&lt;/span> &lt;span class="p">{&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">while&lt;/span> &lt;span class="p">(&lt;/span>&lt;span class="o">!&lt;/span>&lt;span class="n">stoken&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="n">stop_requested&lt;/span>&lt;span class="p">())&lt;/span> &lt;span class="p">{&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">std&lt;/span>&lt;span class="o">::&lt;/span>&lt;span class="n">cout&lt;/span> &lt;span class="o">&amp;lt;&amp;lt;&lt;/span> &lt;span class="s">&amp;#34;Working...&amp;#34;&lt;/span> &lt;span class="o">&amp;lt;&amp;lt;&lt;/span> &lt;span class="n">std&lt;/span>&lt;span class="o">::&lt;/span>&lt;span class="n">endl&lt;/span>&lt;span class="p">;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">std&lt;/span>&lt;span class="o">::&lt;/span>&lt;span class="n">this_thread&lt;/span>&lt;span class="o">::&lt;/span>&lt;span class="n">sleep_for&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">std&lt;/span>&lt;span class="o">::&lt;/span>&lt;span class="n">chrono&lt;/span>&lt;span class="o">::&lt;/span>&lt;span class="n">milliseconds&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="mi">500&lt;/span>&lt;span class="p">));&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="p">}&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">std&lt;/span>&lt;span class="o">::&lt;/span>&lt;span class="n">cout&lt;/span> &lt;span class="o">&amp;lt;&amp;lt;&lt;/span> &lt;span class="s">&amp;#34;Stop requested. Exiting thread.&amp;#34;&lt;/span> &lt;span class="o">&amp;lt;&amp;lt;&lt;/span> &lt;span class="n">std&lt;/span>&lt;span class="o">::&lt;/span>&lt;span class="n">endl&lt;/span>&lt;span class="p">;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="p">});&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">std&lt;/span>&lt;span class="o">::&lt;/span>&lt;span class="n">this_thread&lt;/span>&lt;span class="o">::&lt;/span>&lt;span class="n">sleep_for&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">std&lt;/span>&lt;span class="o">::&lt;/span>&lt;span class="n">chrono&lt;/span>&lt;span class="o">::&lt;/span>&lt;span class="n">seconds&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="mi">2&lt;/span>&lt;span class="p">));&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c1">// स्पष्ट रूप से रद्दीकरण का अनुरोध करना
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">&lt;/span> &lt;span class="n">jt&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="n">request_stop&lt;/span>&lt;span class="p">();&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c1">// jthread के डिस्ट्रक्टर में स्वचालित रूप से join हो जाता है, इसलिए मैन्युअल रूप से join() कॉल करने की आवश्यकता नहीं है
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">&lt;/span> &lt;span class="k">return&lt;/span> &lt;span class="mi">0&lt;/span>&lt;span class="p">;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="p">}&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;hr>
&lt;h2 id="3-डट-रस-data-race-स-बचन-और-सकरनइजशन-मयटकस-mutex-और-लक">3. डेटा रेस (Data Race) से बचना और सिंक्रोनाइज़ेशन: म्यूटेक्स (Mutex) और लॉक
&lt;/h2>&lt;p>जब कई थ्रेड्स एक ही समय में एक ही मेमोरी क्षेत्र (जैसे वेरिएबल) तक पहुँचते हैं, और उनमें से कम से कम एक लिख (write) रहा होता है, तो &lt;strong>डेटा रेस (Data Race)&lt;/strong> होती है। C++ मानक में, डेटा रेस अपरिभाषित व्यवहार (Undefined Behavior) का कारण बनती है। इसे रोकने के लिए, &lt;code>std::mutex&lt;/code> का उपयोग करके पारस्परिक बहिष्करण (mutual exclusion) आवश्यक है।&lt;/p>
&lt;h3 id="stdmutex-और-stdlock_guard">&lt;code>std::mutex&lt;/code> और &lt;code>std::lock_guard&lt;/code>
&lt;/h3>&lt;p>कच्चे (raw) &lt;code>std::mutex::lock()&lt;/code> और &lt;code>unlock()&lt;/code> को मैन्युअल रूप से कॉल करने की अनुशंसा नहीं की जाती है क्योंकि अपवाद (exception) होने पर &lt;code>unlock()&lt;/code> कॉल नहीं हो सकता है, जिससे डेडलॉक (deadlock) का जोखिम होता है। C++ में, हम RAII पैटर्न का उपयोग करके &lt;code>std::lock_guard&lt;/code> (C++11) या &lt;code>std::scoped_lock&lt;/code> (C++17) का उपयोग करते हैं।&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt"> 1
&lt;/span>&lt;span class="lnt"> 2
&lt;/span>&lt;span class="lnt"> 3
&lt;/span>&lt;span class="lnt"> 4
&lt;/span>&lt;span class="lnt"> 5
&lt;/span>&lt;span class="lnt"> 6
&lt;/span>&lt;span class="lnt"> 7
&lt;/span>&lt;span class="lnt"> 8
&lt;/span>&lt;span class="lnt"> 9
&lt;/span>&lt;span class="lnt">10
&lt;/span>&lt;span class="lnt">11
&lt;/span>&lt;span class="lnt">12
&lt;/span>&lt;span class="lnt">13
&lt;/span>&lt;span class="lnt">14
&lt;/span>&lt;span class="lnt">15
&lt;/span>&lt;span class="lnt">16
&lt;/span>&lt;span class="lnt">17
&lt;/span>&lt;span class="lnt">18
&lt;/span>&lt;span class="lnt">19
&lt;/span>&lt;span class="lnt">20
&lt;/span>&lt;span class="lnt">21
&lt;/span>&lt;span class="lnt">22
&lt;/span>&lt;span class="lnt">23
&lt;/span>&lt;span class="lnt">24
&lt;/span>&lt;span class="lnt">25
&lt;/span>&lt;span class="lnt">26
&lt;/span>&lt;span class="lnt">27
&lt;/span>&lt;span class="lnt">28
&lt;/span>&lt;span class="lnt">29
&lt;/span>&lt;span class="lnt">30
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-cpp" data-lang="cpp">&lt;span class="line">&lt;span class="cl">&lt;span class="cp">#include&lt;/span> &lt;span class="cpf">&amp;lt;iostream&amp;gt;&lt;/span>&lt;span class="cp">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="cp">#include&lt;/span> &lt;span class="cpf">&amp;lt;vector&amp;gt;&lt;/span>&lt;span class="cp">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="cp">#include&lt;/span> &lt;span class="cpf">&amp;lt;thread&amp;gt;&lt;/span>&lt;span class="cp">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="cp">#include&lt;/span> &lt;span class="cpf">&amp;lt;mutex&amp;gt;&lt;/span>&lt;span class="cp">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="cp">&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="n">std&lt;/span>&lt;span class="o">::&lt;/span>&lt;span class="n">mutex&lt;/span> &lt;span class="n">g_mutex&lt;/span>&lt;span class="p">;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="kt">int&lt;/span> &lt;span class="n">g_counter&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="mi">0&lt;/span>&lt;span class="p">;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="kt">void&lt;/span> &lt;span class="nf">incrementCounter&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="kt">int&lt;/span> &lt;span class="n">iterations&lt;/span>&lt;span class="p">)&lt;/span> &lt;span class="p">{&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">for&lt;/span> &lt;span class="p">(&lt;/span>&lt;span class="kt">int&lt;/span> &lt;span class="n">i&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="mi">0&lt;/span>&lt;span class="p">;&lt;/span> &lt;span class="n">i&lt;/span> &lt;span class="o">&amp;lt;&lt;/span> &lt;span class="n">iterations&lt;/span>&lt;span class="p">;&lt;/span> &lt;span class="o">++&lt;/span>&lt;span class="n">i&lt;/span>&lt;span class="p">)&lt;/span> &lt;span class="p">{&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c1">// स्कोप से बाहर निकलने पर स्वचालित रूप से unlock हो जाता है
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">&lt;/span> &lt;span class="n">std&lt;/span>&lt;span class="o">::&lt;/span>&lt;span class="n">lock_guard&lt;/span>&lt;span class="o">&amp;lt;&lt;/span>&lt;span class="n">std&lt;/span>&lt;span class="o">::&lt;/span>&lt;span class="n">mutex&lt;/span>&lt;span class="o">&amp;gt;&lt;/span> &lt;span class="n">lock&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">g_mutex&lt;/span>&lt;span class="p">);&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="o">++&lt;/span>&lt;span class="n">g_counter&lt;/span>&lt;span class="p">;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="p">}&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="p">}&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="kt">int&lt;/span> &lt;span class="nf">main&lt;/span>&lt;span class="p">()&lt;/span> &lt;span class="p">{&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">std&lt;/span>&lt;span class="o">::&lt;/span>&lt;span class="n">vector&lt;/span>&lt;span class="o">&amp;lt;&lt;/span>&lt;span class="n">std&lt;/span>&lt;span class="o">::&lt;/span>&lt;span class="kr">thread&lt;/span>&lt;span class="o">&amp;gt;&lt;/span> &lt;span class="n">threads&lt;/span>&lt;span class="p">;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">for&lt;/span> &lt;span class="p">(&lt;/span>&lt;span class="kt">int&lt;/span> &lt;span class="n">i&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="mi">0&lt;/span>&lt;span class="p">;&lt;/span> &lt;span class="n">i&lt;/span> &lt;span class="o">&amp;lt;&lt;/span> &lt;span class="mi">10&lt;/span>&lt;span class="p">;&lt;/span> &lt;span class="o">++&lt;/span>&lt;span class="n">i&lt;/span>&lt;span class="p">)&lt;/span> &lt;span class="p">{&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">threads&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="n">emplace_back&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">incrementCounter&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="mi">10000&lt;/span>&lt;span class="p">);&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="p">}&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">for&lt;/span> &lt;span class="p">(&lt;/span>&lt;span class="k">auto&lt;/span>&lt;span class="o">&amp;amp;&lt;/span> &lt;span class="nl">t&lt;/span> &lt;span class="p">:&lt;/span> &lt;span class="n">threads&lt;/span>&lt;span class="p">)&lt;/span> &lt;span class="p">{&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">t&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="n">join&lt;/span>&lt;span class="p">();&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="p">}&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">std&lt;/span>&lt;span class="o">::&lt;/span>&lt;span class="n">cout&lt;/span> &lt;span class="o">&amp;lt;&amp;lt;&lt;/span> &lt;span class="s">&amp;#34;Final counter value: &amp;#34;&lt;/span> &lt;span class="o">&amp;lt;&amp;lt;&lt;/span> &lt;span class="n">g_counter&lt;/span> &lt;span class="o">&amp;lt;&amp;lt;&lt;/span> &lt;span class="n">std&lt;/span>&lt;span class="o">::&lt;/span>&lt;span class="n">endl&lt;/span>&lt;span class="p">;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c1">// उम्मीद के मुताबिक 100000 होगा
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">&lt;/span> &lt;span class="k">return&lt;/span> &lt;span class="mi">0&lt;/span>&lt;span class="p">;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="p">}&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;h3 id="stdunique_lock">&lt;code>std::unique_lock&lt;/code>
&lt;/h3>&lt;p>&lt;code>std::lock_guard&lt;/code> एक साधारण स्कोप-आधारित लॉक है, लेकिन यदि अधिक लचीले नियंत्रण (देरी से लॉक करना, समय-सीमित लॉक, बीच में अनलॉक करना आदि) की आवश्यकता है, तो &lt;code>std::unique_lock&lt;/code> का उपयोग किया जाता है। &lt;code>std::condition_variable&lt;/code> (जिसे आगे समझाया गया है) के लिए &lt;code>std::unique_lock&lt;/code> का होना आवश्यक है।&lt;/p>
&lt;hr>
&lt;h2 id="4-थरडस-क-बच-सचर-stdcondition_variable">4. थ्रेड्स के बीच संचार: &lt;code>std::condition_variable&lt;/code>
&lt;/h2>&lt;p>&amp;ldquo;उत्पादक-उपभोक्ता पैटर्न (Producer-Consumer Pattern)&amp;rdquo; को लागू करने के लिए, जहां एक थ्रेड एक निश्चित शर्त पूरी होने तक प्रतीक्षा करता है, और दूसरा थ्रेड शर्त पूरी होने पर उसे सूचित करता है, हम &lt;code>std::condition_variable&lt;/code> का उपयोग करते हैं।&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt"> 1
&lt;/span>&lt;span class="lnt"> 2
&lt;/span>&lt;span class="lnt"> 3
&lt;/span>&lt;span class="lnt"> 4
&lt;/span>&lt;span class="lnt"> 5
&lt;/span>&lt;span class="lnt"> 6
&lt;/span>&lt;span class="lnt"> 7
&lt;/span>&lt;span class="lnt"> 8
&lt;/span>&lt;span class="lnt"> 9
&lt;/span>&lt;span class="lnt">10
&lt;/span>&lt;span class="lnt">11
&lt;/span>&lt;span class="lnt">12
&lt;/span>&lt;span class="lnt">13
&lt;/span>&lt;span class="lnt">14
&lt;/span>&lt;span class="lnt">15
&lt;/span>&lt;span class="lnt">16
&lt;/span>&lt;span class="lnt">17
&lt;/span>&lt;span class="lnt">18
&lt;/span>&lt;span class="lnt">19
&lt;/span>&lt;span class="lnt">20
&lt;/span>&lt;span class="lnt">21
&lt;/span>&lt;span class="lnt">22
&lt;/span>&lt;span class="lnt">23
&lt;/span>&lt;span class="lnt">24
&lt;/span>&lt;span class="lnt">25
&lt;/span>&lt;span class="lnt">26
&lt;/span>&lt;span class="lnt">27
&lt;/span>&lt;span class="lnt">28
&lt;/span>&lt;span class="lnt">29
&lt;/span>&lt;span class="lnt">30
&lt;/span>&lt;span class="lnt">31
&lt;/span>&lt;span class="lnt">32
&lt;/span>&lt;span class="lnt">33
&lt;/span>&lt;span class="lnt">34
&lt;/span>&lt;span class="lnt">35
&lt;/span>&lt;span class="lnt">36
&lt;/span>&lt;span class="lnt">37
&lt;/span>&lt;span class="lnt">38
&lt;/span>&lt;span class="lnt">39
&lt;/span>&lt;span class="lnt">40
&lt;/span>&lt;span class="lnt">41
&lt;/span>&lt;span class="lnt">42
&lt;/span>&lt;span class="lnt">43
&lt;/span>&lt;span class="lnt">44
&lt;/span>&lt;span class="lnt">45
&lt;/span>&lt;span class="lnt">46
&lt;/span>&lt;span class="lnt">47
&lt;/span>&lt;span class="lnt">48
&lt;/span>&lt;span class="lnt">49
&lt;/span>&lt;span class="lnt">50
&lt;/span>&lt;span class="lnt">51
&lt;/span>&lt;span class="lnt">52
&lt;/span>&lt;span class="lnt">53
&lt;/span>&lt;span class="lnt">54
&lt;/span>&lt;span class="lnt">55
&lt;/span>&lt;span class="lnt">56
&lt;/span>&lt;span class="lnt">57
&lt;/span>&lt;span class="lnt">58
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-cpp" data-lang="cpp">&lt;span class="line">&lt;span class="cl">&lt;span class="cp">#include&lt;/span> &lt;span class="cpf">&amp;lt;iostream&amp;gt;&lt;/span>&lt;span class="cp">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="cp">#include&lt;/span> &lt;span class="cpf">&amp;lt;thread&amp;gt;&lt;/span>&lt;span class="cp">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="cp">#include&lt;/span> &lt;span class="cpf">&amp;lt;mutex&amp;gt;&lt;/span>&lt;span class="cp">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="cp">#include&lt;/span> &lt;span class="cpf">&amp;lt;condition_variable&amp;gt;&lt;/span>&lt;span class="cp">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="cp">#include&lt;/span> &lt;span class="cpf">&amp;lt;queue&amp;gt;&lt;/span>&lt;span class="cp">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="cp">&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="n">std&lt;/span>&lt;span class="o">::&lt;/span>&lt;span class="n">mutex&lt;/span> &lt;span class="n">g_mtx&lt;/span>&lt;span class="p">;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="n">std&lt;/span>&lt;span class="o">::&lt;/span>&lt;span class="n">condition_variable&lt;/span> &lt;span class="n">g_cv&lt;/span>&lt;span class="p">;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="n">std&lt;/span>&lt;span class="o">::&lt;/span>&lt;span class="n">queue&lt;/span>&lt;span class="o">&amp;lt;&lt;/span>&lt;span class="kt">int&lt;/span>&lt;span class="o">&amp;gt;&lt;/span> &lt;span class="n">g_dataQueue&lt;/span>&lt;span class="p">;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="kt">bool&lt;/span> &lt;span class="n">g_isFinished&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="nb">false&lt;/span>&lt;span class="p">;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="kt">void&lt;/span> &lt;span class="nf">producer&lt;/span>&lt;span class="p">()&lt;/span> &lt;span class="p">{&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">for&lt;/span> &lt;span class="p">(&lt;/span>&lt;span class="kt">int&lt;/span> &lt;span class="n">i&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="mi">1&lt;/span>&lt;span class="p">;&lt;/span> &lt;span class="n">i&lt;/span> &lt;span class="o">&amp;lt;=&lt;/span> &lt;span class="mi">5&lt;/span>&lt;span class="p">;&lt;/span> &lt;span class="o">++&lt;/span>&lt;span class="n">i&lt;/span>&lt;span class="p">)&lt;/span> &lt;span class="p">{&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">std&lt;/span>&lt;span class="o">::&lt;/span>&lt;span class="n">this_thread&lt;/span>&lt;span class="o">::&lt;/span>&lt;span class="n">sleep_for&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">std&lt;/span>&lt;span class="o">::&lt;/span>&lt;span class="n">chrono&lt;/span>&lt;span class="o">::&lt;/span>&lt;span class="n">milliseconds&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="mi">200&lt;/span>&lt;span class="p">));&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="p">{&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">std&lt;/span>&lt;span class="o">::&lt;/span>&lt;span class="n">lock_guard&lt;/span>&lt;span class="o">&amp;lt;&lt;/span>&lt;span class="n">std&lt;/span>&lt;span class="o">::&lt;/span>&lt;span class="n">mutex&lt;/span>&lt;span class="o">&amp;gt;&lt;/span> &lt;span class="n">lock&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">g_mtx&lt;/span>&lt;span class="p">);&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">g_dataQueue&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="n">push&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">i&lt;/span>&lt;span class="p">);&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">std&lt;/span>&lt;span class="o">::&lt;/span>&lt;span class="n">cout&lt;/span> &lt;span class="o">&amp;lt;&amp;lt;&lt;/span> &lt;span class="s">&amp;#34;Produced: &amp;#34;&lt;/span> &lt;span class="o">&amp;lt;&amp;lt;&lt;/span> &lt;span class="n">i&lt;/span> &lt;span class="o">&amp;lt;&amp;lt;&lt;/span> &lt;span class="n">std&lt;/span>&lt;span class="o">::&lt;/span>&lt;span class="n">endl&lt;/span>&lt;span class="p">;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="p">}&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">g_cv&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="n">notify_one&lt;/span>&lt;span class="p">();&lt;/span> &lt;span class="c1">// उपभोक्ता (consumer) को सूचित करना
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">&lt;/span> &lt;span class="p">}&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="p">{&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">std&lt;/span>&lt;span class="o">::&lt;/span>&lt;span class="n">lock_guard&lt;/span>&lt;span class="o">&amp;lt;&lt;/span>&lt;span class="n">std&lt;/span>&lt;span class="o">::&lt;/span>&lt;span class="n">mutex&lt;/span>&lt;span class="o">&amp;gt;&lt;/span> &lt;span class="n">lock&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">g_mtx&lt;/span>&lt;span class="p">);&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">g_isFinished&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="nb">true&lt;/span>&lt;span class="p">;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="p">}&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">g_cv&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="n">notify_one&lt;/span>&lt;span class="p">();&lt;/span> &lt;span class="c1">// पूर्ण होने की सूचना देना
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">&lt;/span>&lt;span class="p">}&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="kt">void&lt;/span> &lt;span class="nf">consumer&lt;/span>&lt;span class="p">()&lt;/span> &lt;span class="p">{&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">while&lt;/span> &lt;span class="p">(&lt;/span>&lt;span class="nb">true&lt;/span>&lt;span class="p">)&lt;/span> &lt;span class="p">{&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">std&lt;/span>&lt;span class="o">::&lt;/span>&lt;span class="n">unique_lock&lt;/span>&lt;span class="o">&amp;lt;&lt;/span>&lt;span class="n">std&lt;/span>&lt;span class="o">::&lt;/span>&lt;span class="n">mutex&lt;/span>&lt;span class="o">&amp;gt;&lt;/span> &lt;span class="n">lock&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">g_mtx&lt;/span>&lt;span class="p">);&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c1">// शर्त पूरी होने तक प्रतीक्षा करें (कतार खाली नहीं है, या समाप्ति ध्वज (flag) सेट है)
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">&lt;/span> &lt;span class="c1">// स्पूरियस वेकअप (Spurious Wakeup) को रोकने के लिए लैम्ब्डा एक्सप्रेशन के साथ शर्त निर्दिष्ट करें
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">&lt;/span> &lt;span class="n">g_cv&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="n">wait&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">lock&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="p">[]{&lt;/span> &lt;span class="k">return&lt;/span> &lt;span class="o">!&lt;/span>&lt;span class="n">g_dataQueue&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="n">empty&lt;/span>&lt;span class="p">()&lt;/span> &lt;span class="o">||&lt;/span> &lt;span class="n">g_isFinished&lt;/span>&lt;span class="p">;&lt;/span> &lt;span class="p">});&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">while&lt;/span> &lt;span class="p">(&lt;/span>&lt;span class="o">!&lt;/span>&lt;span class="n">g_dataQueue&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="n">empty&lt;/span>&lt;span class="p">())&lt;/span> &lt;span class="p">{&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="kt">int&lt;/span> &lt;span class="n">val&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">g_dataQueue&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="n">front&lt;/span>&lt;span class="p">();&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">g_dataQueue&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="n">pop&lt;/span>&lt;span class="p">();&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c1">// अनलॉक करें और भारी प्रोसेसिंग (यहाँ केवल आउटपुट) करें
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">&lt;/span> &lt;span class="n">lock&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="n">unlock&lt;/span>&lt;span class="p">();&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">std&lt;/span>&lt;span class="o">::&lt;/span>&lt;span class="n">cout&lt;/span> &lt;span class="o">&amp;lt;&amp;lt;&lt;/span> &lt;span class="s">&amp;#34;Consumed: &amp;#34;&lt;/span> &lt;span class="o">&amp;lt;&amp;lt;&lt;/span> &lt;span class="n">val&lt;/span> &lt;span class="o">&amp;lt;&amp;lt;&lt;/span> &lt;span class="n">std&lt;/span>&lt;span class="o">::&lt;/span>&lt;span class="n">endl&lt;/span>&lt;span class="p">;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">lock&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="n">lock&lt;/span>&lt;span class="p">();&lt;/span> &lt;span class="c1">// लॉक फिर से प्राप्त करें
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">&lt;/span> &lt;span class="p">}&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">if&lt;/span> &lt;span class="p">(&lt;/span>&lt;span class="n">g_isFinished&lt;/span> &lt;span class="o">&amp;amp;&amp;amp;&lt;/span> &lt;span class="n">g_dataQueue&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="n">empty&lt;/span>&lt;span class="p">())&lt;/span> &lt;span class="p">{&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">break&lt;/span>&lt;span class="p">;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="p">}&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="p">}&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="p">}&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="kt">int&lt;/span> &lt;span class="nf">main&lt;/span>&lt;span class="p">()&lt;/span> &lt;span class="p">{&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">std&lt;/span>&lt;span class="o">::&lt;/span>&lt;span class="kr">thread&lt;/span> &lt;span class="n">t1&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">producer&lt;/span>&lt;span class="p">);&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">std&lt;/span>&lt;span class="o">::&lt;/span>&lt;span class="kr">thread&lt;/span> &lt;span class="n">t2&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">consumer&lt;/span>&lt;span class="p">);&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">t1&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="n">join&lt;/span>&lt;span class="p">();&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">t2&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="n">join&lt;/span>&lt;span class="p">();&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">return&lt;/span> &lt;span class="mi">0&lt;/span>&lt;span class="p">;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="p">}&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>इस उदाहरण में, &lt;code>std::condition_variable::wait&lt;/code> थ्रेड को तब तक स्लीप अवस्था में रखता है जब तक कि शर्त पूरी नहीं हो जाती, जिससे CPU संसाधनों की अनावश्यक खपत (व्यस्त लूप / busy loop) से बचा जा सकता है।&lt;/p>
&lt;hr>
&lt;h2 id="5-उचच-सतरय-एसकरनस-परससग-stdfuture-stdpromise-stdasync">5. उच्च-स्तरीय एसिंक्रोनस प्रोसेसिंग: &lt;code>std::future&lt;/code>, &lt;code>std::promise&lt;/code>, &lt;code>std::async&lt;/code>
&lt;/h2>&lt;p>अब तक चर्चा किए गए &lt;code>std::thread&lt;/code> और &lt;code>std::mutex&lt;/code> शक्तिशाली हैं, लेकिन वे OS के निम्न-स्तरीय (low-level) थ्रेड तंत्र को सीधे C++ में लाते हैं, जिससे परिणाम प्राप्त करने या अपवादों का प्रचार (exception propagation) करने के लिए कोड बोझिल हो जाता है। यदि आप एक रिटर्न वैल्यू (return value) के साथ कंकरेंट प्रोसेसिंग या उच्च-स्तरीय एसिंक्रोनस प्रोसेसिंग करना चाहते हैं, तो &lt;code>&amp;lt;future&amp;gt;&lt;/code> हेडर की सुविधाओं का उपयोग करें।&lt;/p>
&lt;h3 id="stdpromise-और-stdfuture">&lt;code>std::promise&lt;/code> और &lt;code>std::future&lt;/code>
&lt;/h3>&lt;p>&lt;code>std::promise&lt;/code> उस पक्ष का प्रतिनिधित्व करता है जो परिणाम &amp;ldquo;सेट&amp;rdquo; करता है, और &lt;code>std::future&lt;/code> उस पक्ष का प्रतिनिधित्व करता है जो परिणाम &amp;ldquo;प्राप्त&amp;rdquo; करता है। ये थ्रेड्स के बीच परिणाम और अपवाद पारित करने के लिए एक सुरक्षित चैनल के रूप में कार्य करते हैं।&lt;/p>
&lt;h3 id="stdasync-क-उपयग-करक-टसक-आधरत-ककरट-परससग">&lt;code>std::async&lt;/code> का उपयोग करके टास्क-आधारित कंकरेंट प्रोसेसिंग
&lt;/h3>&lt;p>C++ में एसिंक्रोनस कार्यों को निष्पादित करने का सबसे अनुशंसित तरीका &lt;code>std::async&lt;/code> का उपयोग करना है। &lt;code>std::async&lt;/code> एक कार्य को एसिंक्रोनस रूप से निष्पादित करता है और परिणाम प्राप्त करने के लिए एक &lt;code>std::future&lt;/code> लौटाता है।&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt"> 1
&lt;/span>&lt;span class="lnt"> 2
&lt;/span>&lt;span class="lnt"> 3
&lt;/span>&lt;span class="lnt"> 4
&lt;/span>&lt;span class="lnt"> 5
&lt;/span>&lt;span class="lnt"> 6
&lt;/span>&lt;span class="lnt"> 7
&lt;/span>&lt;span class="lnt"> 8
&lt;/span>&lt;span class="lnt"> 9
&lt;/span>&lt;span class="lnt">10
&lt;/span>&lt;span class="lnt">11
&lt;/span>&lt;span class="lnt">12
&lt;/span>&lt;span class="lnt">13
&lt;/span>&lt;span class="lnt">14
&lt;/span>&lt;span class="lnt">15
&lt;/span>&lt;span class="lnt">16
&lt;/span>&lt;span class="lnt">17
&lt;/span>&lt;span class="lnt">18
&lt;/span>&lt;span class="lnt">19
&lt;/span>&lt;span class="lnt">20
&lt;/span>&lt;span class="lnt">21
&lt;/span>&lt;span class="lnt">22
&lt;/span>&lt;span class="lnt">23
&lt;/span>&lt;span class="lnt">24
&lt;/span>&lt;span class="lnt">25
&lt;/span>&lt;span class="lnt">26
&lt;/span>&lt;span class="lnt">27
&lt;/span>&lt;span class="lnt">28
&lt;/span>&lt;span class="lnt">29
&lt;/span>&lt;span class="lnt">30
&lt;/span>&lt;span class="lnt">31
&lt;/span>&lt;span class="lnt">32
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-cpp" data-lang="cpp">&lt;span class="line">&lt;span class="cl">&lt;span class="cp">#include&lt;/span> &lt;span class="cpf">&amp;lt;iostream&amp;gt;&lt;/span>&lt;span class="cp">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="cp">#include&lt;/span> &lt;span class="cpf">&amp;lt;future&amp;gt;&lt;/span>&lt;span class="cp">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="cp">#include&lt;/span> &lt;span class="cpf">&amp;lt;chrono&amp;gt;&lt;/span>&lt;span class="cp">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="cp">&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="kt">int&lt;/span> &lt;span class="nf">complexCalculation&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="kt">int&lt;/span> &lt;span class="n">x&lt;/span>&lt;span class="p">)&lt;/span> &lt;span class="p">{&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">std&lt;/span>&lt;span class="o">::&lt;/span>&lt;span class="n">cout&lt;/span> &lt;span class="o">&amp;lt;&amp;lt;&lt;/span> &lt;span class="s">&amp;#34;Calculation started on thread: &amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="o">&amp;lt;&amp;lt;&lt;/span> &lt;span class="n">std&lt;/span>&lt;span class="o">::&lt;/span>&lt;span class="n">this_thread&lt;/span>&lt;span class="o">::&lt;/span>&lt;span class="n">get_id&lt;/span>&lt;span class="p">()&lt;/span> &lt;span class="o">&amp;lt;&amp;lt;&lt;/span> &lt;span class="n">std&lt;/span>&lt;span class="o">::&lt;/span>&lt;span class="n">endl&lt;/span>&lt;span class="p">;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">std&lt;/span>&lt;span class="o">::&lt;/span>&lt;span class="n">this_thread&lt;/span>&lt;span class="o">::&lt;/span>&lt;span class="n">sleep_for&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">std&lt;/span>&lt;span class="o">::&lt;/span>&lt;span class="n">chrono&lt;/span>&lt;span class="o">::&lt;/span>&lt;span class="n">seconds&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="mi">2&lt;/span>&lt;span class="p">));&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">if&lt;/span> &lt;span class="p">(&lt;/span>&lt;span class="n">x&lt;/span> &lt;span class="o">&amp;lt;&lt;/span> &lt;span class="mi">0&lt;/span>&lt;span class="p">)&lt;/span> &lt;span class="p">{&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">throw&lt;/span> &lt;span class="n">std&lt;/span>&lt;span class="o">::&lt;/span>&lt;span class="n">invalid_argument&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s">&amp;#34;x must be positive&amp;#34;&lt;/span>&lt;span class="p">);&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="p">}&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">return&lt;/span> &lt;span class="n">x&lt;/span> &lt;span class="o">*&lt;/span> &lt;span class="mi">42&lt;/span>&lt;span class="p">;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="p">}&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="kt">int&lt;/span> &lt;span class="nf">main&lt;/span>&lt;span class="p">()&lt;/span> &lt;span class="p">{&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">std&lt;/span>&lt;span class="o">::&lt;/span>&lt;span class="n">cout&lt;/span> &lt;span class="o">&amp;lt;&amp;lt;&lt;/span> &lt;span class="s">&amp;#34;Main thread id: &amp;#34;&lt;/span> &lt;span class="o">&amp;lt;&amp;lt;&lt;/span> &lt;span class="n">std&lt;/span>&lt;span class="o">::&lt;/span>&lt;span class="n">this_thread&lt;/span>&lt;span class="o">::&lt;/span>&lt;span class="n">get_id&lt;/span>&lt;span class="p">()&lt;/span> &lt;span class="o">&amp;lt;&amp;lt;&lt;/span> &lt;span class="n">std&lt;/span>&lt;span class="o">::&lt;/span>&lt;span class="n">endl&lt;/span>&lt;span class="p">;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c1">// बलपूर्वक एक अलग थ्रेड में निष्पादित करने के लिए std::launch::async निर्दिष्ट करें
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">&lt;/span> &lt;span class="n">std&lt;/span>&lt;span class="o">::&lt;/span>&lt;span class="n">future&lt;/span>&lt;span class="o">&amp;lt;&lt;/span>&lt;span class="kt">int&lt;/span>&lt;span class="o">&amp;gt;&lt;/span> &lt;span class="n">resultFuture&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">std&lt;/span>&lt;span class="o">::&lt;/span>&lt;span class="n">async&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">std&lt;/span>&lt;span class="o">::&lt;/span>&lt;span class="n">launch&lt;/span>&lt;span class="o">::&lt;/span>&lt;span class="n">async&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">complexCalculation&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="mi">10&lt;/span>&lt;span class="p">);&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">std&lt;/span>&lt;span class="o">::&lt;/span>&lt;span class="n">cout&lt;/span> &lt;span class="o">&amp;lt;&amp;lt;&lt;/span> &lt;span class="s">&amp;#34;Main thread is doing other work...&amp;#34;&lt;/span> &lt;span class="o">&amp;lt;&amp;lt;&lt;/span> &lt;span class="n">std&lt;/span>&lt;span class="o">::&lt;/span>&lt;span class="n">endl&lt;/span>&lt;span class="p">;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">try&lt;/span> &lt;span class="p">{&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c1">// get() कॉल करने से वर्तमान थ्रेड तब तक ब्लॉक रहेगा जब तक गणना पूरी नहीं हो जाती
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">&lt;/span> &lt;span class="kt">int&lt;/span> &lt;span class="n">result&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">resultFuture&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="n">get&lt;/span>&lt;span class="p">();&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">std&lt;/span>&lt;span class="o">::&lt;/span>&lt;span class="n">cout&lt;/span> &lt;span class="o">&amp;lt;&amp;lt;&lt;/span> &lt;span class="s">&amp;#34;Result: &amp;#34;&lt;/span> &lt;span class="o">&amp;lt;&amp;lt;&lt;/span> &lt;span class="n">result&lt;/span> &lt;span class="o">&amp;lt;&amp;lt;&lt;/span> &lt;span class="n">std&lt;/span>&lt;span class="o">::&lt;/span>&lt;span class="n">endl&lt;/span>&lt;span class="p">;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="p">}&lt;/span> &lt;span class="k">catch&lt;/span> &lt;span class="p">(&lt;/span>&lt;span class="k">const&lt;/span> &lt;span class="n">std&lt;/span>&lt;span class="o">::&lt;/span>&lt;span class="n">exception&lt;/span>&lt;span class="o">&amp;amp;&lt;/span> &lt;span class="n">e&lt;/span>&lt;span class="p">)&lt;/span> &lt;span class="p">{&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">std&lt;/span>&lt;span class="o">::&lt;/span>&lt;span class="n">cerr&lt;/span> &lt;span class="o">&amp;lt;&amp;lt;&lt;/span> &lt;span class="s">&amp;#34;Exception caught: &amp;#34;&lt;/span> &lt;span class="o">&amp;lt;&amp;lt;&lt;/span> &lt;span class="n">e&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="n">what&lt;/span>&lt;span class="p">()&lt;/span> &lt;span class="o">&amp;lt;&amp;lt;&lt;/span> &lt;span class="n">std&lt;/span>&lt;span class="o">::&lt;/span>&lt;span class="n">endl&lt;/span>&lt;span class="p">;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="p">}&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">return&lt;/span> &lt;span class="mi">0&lt;/span>&lt;span class="p">;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="p">}&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>&lt;code>std::async&lt;/code> का व्यवहार नीचे दिए गए अनुक्रम आरेख (sequence diagram) में दिखाया गया है।&lt;/p>
&lt;div class="mermaid">sequenceDiagram
participant Main as "मुख्य थ्रेड (Main Thread)"
participant Async as "std::async वर्कर (std::async Worker)"
Main->>Async: "std::async(std::launch::async, ...)"
activate Async
Note over Main: "अन्य कार्य करें (Do other work...)"
Main->>Async: "future.get() (तैयार होने तक ब्लॉक करता है)"
Note right of Async: "गणनाएँ (Computations...)"
Async-->>Main: "परिणाम लौटाएँ या अपवाद फेंकें (Return Result or Throw Exception)"
deactivate Async&lt;/div>
&lt;p>&lt;code>std::async&lt;/code> के पहले तर्क (argument), लॉन्च पॉलिसी (Launch Policy), के दो प्रकार हैं:&lt;/p>
&lt;ul>
&lt;li>&lt;code>std::launch::async&lt;/code>: हमेशा एक नया थ्रेड बनाता है (या थ्रेड पूल से असाइन करता है) और एसिंक्रोनस रूप से निष्पादित करता है।&lt;/li>
&lt;li>&lt;code>std::launch::deferred&lt;/code>: आलसी मूल्यांकन (Lazy evaluation)। जब &lt;code>future.get()&lt;/code> या &lt;code>future.wait()&lt;/code> को कॉल किया जाता है, तो यह कॉलिंग थ्रेड में सिंक्रोनस रूप से निष्पादित होता है।&lt;/li>
&lt;/ul>
&lt;p>यदि डिफ़ॉल्ट रूप से छोड़ दिया जाता है (निर्दिष्ट नहीं किया गया है), तो यह कार्यान्वयन पर निर्भर (implementation-dependent) होता है, और सिस्टम के लोड की स्थिति के आधार पर कोई एक चुना जाता है। यदि आप एसिंक्रोनस निष्पादन सुनिश्चित करना चाहते हैं, স্ক্রिप्त एसिंक्रोनस निष्पादन सुनिश्चित करना चाहते हैं, तो स्पष्ट रूप से &lt;code>std::launch::async&lt;/code> निर्दिष्ट करें।&lt;/p>
&lt;hr>
&lt;h2 id="6-थरड-पल-thread-pool-क-अवधरण">6. थ्रेड पूल (Thread Pool) की अवधारणा
&lt;/h2>&lt;p>यदि आप हर बार &lt;code>std::async&lt;/code> को कॉल करते हैं, या लूप के भीतर बार-बार &lt;code>std::thread&lt;/code> बनाते और नष्ट करते हैं, तो थ्रेड कॉन्टेक्स्ट स्विचिंग और OS संसाधन आवंटन के कारण होने वाला ओवरहेड महत्वपूर्ण हो जाता है। विशेष रूप से जब बड़ी संख्या में छोटे कार्यों (fine-grained tasks) को संसाधित किया जाता है, तो थ्रेड पूल (Thread Pool) का उपयोग आवश्यक है।&lt;/p>
&lt;p>थ्रेड पूल एक ऐसा आर्किटेक्चर है जहाँ एप्लिकेशन के स्टार्टअप पर एक निश्चित संख्या में वर्कर (Worker) थ्रेड पहले से बना लिए जाते हैं, कार्यों को एक कतार (Queue) में रखा जाता है, और उपलब्ध वर्कर थ्रेड्स कार्यों को कतार से निकालकर क्रमिक रूप से संसाधित करते हैं।&lt;/p>
&lt;div class="mermaid">graph TD
Client["क्लाइंट / मुख्य थ्रेड (Client / Main Thread)"] -->|कार्य कतार में डालें (Push Task)| Queue["कार्य कतार (Task Queue)"]
Queue -->|कार्य निकालें (Pop Task)| W1["वर्कर थ्रेड 1 (Worker Thread 1)"]
Queue -->|कार्य निकालें (Pop Task)| W2["वर्कर थ्रेड 2 (Worker Thread 2)"]
Queue -->|कार्य निकालें (Pop Task)| W3["वर्कर थ्रेड N (Worker Thread N)"]
W1 --> Exec["निष्पादन और फ्यूचर रिटर्न (Execution &amp; Return Future)"]
W2 --> Exec
W3 --> Exec&lt;/div>
&lt;p>हालांकि C++ मानक लाइब्रेरी (C++23 तक) में एक मानक थ्रेड पूल क्लास नहीं है, लेकिन &lt;code>std::thread&lt;/code>, &lt;code>std::mutex&lt;/code>, &lt;code>std::condition_variable&lt;/code>, &lt;code>std::function&lt;/code>, और &lt;code>std::packaged_task&lt;/code> को मिलाकर कुछ दर्जन पंक्तियों (lines) में एक कुशल थ्रेड पूल लागू करना संभव है। वास्तविक उत्पादन वातावरण (production environment) में, &lt;code>Boost.Asio&lt;/code> के एसिंक्रोनस I/O या थर्ड-पार्टी लाइब्रेरी का उपयोग करना आम बात है।&lt;/p>
&lt;hr>
&lt;h2 id="7-परदरशन-performance-और-सकलबलट-scalability-पर-वचर">7. प्रदर्शन (Performance) और स्केलेबिलिटी (Scalability) पर विचार
&lt;/h2>&lt;p>मल्टीथ्रेडिंग प्रोग्रामिंग में सर्वोत्तम प्रदर्शन प्राप्त करने के लिए, न केवल कोड के समानांतरकरण पर बल्कि हार्डवेयर आर्किटेक्चर पर भी ध्यान देना आवश्यक है।&lt;/p>
&lt;ul>
&lt;li>&lt;strong>फॉल्स शेयरिंग (False Sharing):&lt;/strong>
भले ही कई थ्रेड्स अलग-अलग वेरिएबल्स को अपडेट कर रहे हों, यदि वे वेरिएबल्स CPU की एक ही कैश लाइन (cache line - आमतौर पर 64 बाइट्स) में स्थित हैं, तो कैश कोहेरेंसी (cache coherency) बनाए रखने के लिए अनावश्यक मेमोरी सिंक्रोनाइज़ेशन होता है, जिससे प्रदर्शन में भारी गिरावट आती है। इसे रोकने के लिए, &lt;code>alignas&lt;/code> स्पेसिफायर (specifier) का उपयोग करके वेरिएबल्स को कैश लाइन की सीमाओं पर संरेखित (align) करना आवश्यक है।&lt;/li>
&lt;li>&lt;strong>लॉक-फ्री (Lock-Free) और &lt;code>std::atomic&lt;/code>:&lt;/strong>
म्यूटेक्स के लॉक/अनलॉक के ओवरहेड से बचने के लिए, &lt;code>&amp;lt;atomic&amp;gt;&lt;/code> का उपयोग करके अविभाज्य संचालन (atomic operations, जैसे कि Compare-And-Swap) या लॉक-फ्री डेटा स्ट्रक्चर शुरू करने पर विचार किया जाता है। हालाँकि, इसके लिए मेमोरी ऑर्डर (&lt;code>std::memory_order&lt;/code>) की सही समझ की आवश्यकता होती है, और इसे लागू करना बहुत कठिन है। इसलिए, आमतौर पर सावधानीपूर्वक प्रदर्शन मापन (performance measurement) के बाद ही इसे पेश किया जाता है, जब इसकी सख्त आवश्यकता हो।&lt;/li>
&lt;/ul>
&lt;hr>
&lt;h2 id="8-नषकरष">8. निष्कर्ष
&lt;/h2>&lt;p>हमने C++ में मल्टीथ्रेडिंग और एसिंक्रोनस प्रोग्रामिंग के बारे में बुनियादी बातों से लेकर C++20 की नवीनतम सुविधाओं तक चर्चा की है। महत्वपूर्ण बिंदु इस प्रकार हैं:&lt;/p>
&lt;ol>
&lt;li>&lt;strong>मूल रूप से &lt;code>std::async&lt;/code> का उपयोग करें:&lt;/strong> एकल एसिंक्रोनस कार्यों और परिणाम लौटाने वाले कंकरेंट प्रोसेसिंग के लिए, थ्रेड्स को मैन्युअल रूप से प्रबंधित करने के बजाय सुरक्षित &lt;code>std::async&lt;/code> और &lt;code>std::future&lt;/code> का उपयोग करें।&lt;/li>
&lt;li>&lt;strong>थ्रेड प्रबंधन के लिए &lt;code>std::jthread&lt;/code>:&lt;/strong> पृष्ठभूमि में लंबे समय तक चलने वाले थ्रेड्स के लिए, C++20 के &lt;code>std::jthread&lt;/code> का उपयोग करें ताकि सुरक्षित समाप्ति प्रक्रिया सुनिश्चित हो सके।&lt;/li>
&lt;li>&lt;strong>सिंक्रोनाइज़ेशन के लिए RAII का लाभ उठाएं:&lt;/strong> डेटा रेस को रोकने के लिए म्यूटेक्स लॉक हमेशा &lt;code>std::lock_guard&lt;/code> या &lt;code>std::unique_lock&lt;/code> के माध्यम से किया जाना चाहिए।&lt;/li>
&lt;li>&lt;strong>ओवरहेड के प्रति सचेत रहें:&lt;/strong> थ्रेड्स के अत्यधिक निर्माण से बचें, और यदि आवश्यक हो तो थ्रेड पूल आर्किटेक्चर पेश करें।&lt;/li>
&lt;/ol>
&lt;p>कंकरेंट प्रोसेसिंग बग (जैसे डेडलॉक, डेटा रेस) की पुनरावृत्ति (reproducibility) कम होती है और इन्हें डीबग करना सबसे कठिन होता है। थ्रेड सुरक्षा (thread safety) के प्रति हमेशा सचेत रहें और आधुनिक C++ के साथ मजबूत और तेज़ सिस्टम विकास प्राप्त करने के लिए उचित मानक लाइब्रेरी टूल का चयन करें।&lt;/p></description></item><item><title>मेमोरी लीक को रोकने के लिए स्मार्ट पॉइंटर्स (std::unique_ptr / shared_ptr) का उपयोग गाइड</title><link>http://kenji.blog/hi/p/cpp-smart-pointers-guide-unique-shared-ptr/</link><pubDate>Sat, 12 Sep 2026 07:00:00 +0900</pubDate><guid>http://kenji.blog/hi/p/cpp-smart-pointers-guide-unique-shared-ptr/</guid><description>&lt;img src="http://kenji.blog/p/cpp-smart-pointers-guide-unique-shared-ptr/img/eyecatch.jpg" alt="Featured image of post मेमोरी लीक को रोकने के लिए स्मार्ट पॉइंटर्स (std::unique_ptr / shared_ptr) का उपयोग गाइड" />&lt;p>C++ में मेमोरी प्रबंधन लंबे समय से डेवलपर्स के लिए सबसे बड़ी चुनौतियों में से एक रहा है। मैन्युअल &lt;code>new&lt;/code> और &lt;code>delete&lt;/code> पर निर्भर पारंपरिक मेमोरी प्रबंधन शैली, मेमोरी लीक, डैंगलिंग पॉइंटर्स और डबल फ्री जैसे गंभीर बग्स का कारण बनती थी। हालाँकि, मॉडर्न C++ (C++11 और उसके बाद) के आगमन के साथ, स्थिति नाटकीय रूप से बदल गई है। इसका मुख्य केंद्र &amp;ldquo;स्मार्ट पॉइंटर्स (Smart Pointers)&amp;rdquo; है।&lt;/p>
&lt;p>इस लेख में, हम मेमोरी लीक को जड़ से खत्म करने और सुरक्षित तथा कुशल संसाधन प्रबंधन प्राप्त करने के लिए शक्तिशाली उपकरणों, जैसे &lt;code>std::unique_ptr&lt;/code>, &lt;code>std::shared_ptr&lt;/code> और &lt;code>std::weak_ptr&lt;/code> के तंत्र और उन्नत उपयोग तकनीकों के बारे में विस्तार से चर्चा करेंगे। इसमें आंतरिक कार्यान्वयन (कंट्रोल ब्लॉक और एटॉमिक ऑपरेशंस), प्रदर्शन पर प्रभाव, और गणितीय मॉडल का उपयोग करके संदर्भ गणना (reference counting) के सूत्रीकरण पर भी गहराई से बात की जाएगी।&lt;/p>
&lt;h2 id="1-परचय-c-ममर-परबधन-क-अधकर-यग-और-मडरन-c-क-सबह">1. परिचय: C++ मेमोरी प्रबंधन का अंधकार युग और मॉडर्न C++ की सुबह
&lt;/h2>&lt;p>पहले के C++ विकास में, डेवलपर्स खुद ही हीप पर आवंटित मेमोरी को मुक्त करने के लिए जिम्मेदार होते थे।&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt">1
&lt;/span>&lt;span class="lnt">2
&lt;/span>&lt;span class="lnt">3
&lt;/span>&lt;span class="lnt">4
&lt;/span>&lt;span class="lnt">5
&lt;/span>&lt;span class="lnt">6
&lt;/span>&lt;span class="lnt">7
&lt;/span>&lt;span class="lnt">8
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-cpp" data-lang="cpp">&lt;span class="line">&lt;span class="cl">&lt;span class="kt">void&lt;/span> &lt;span class="nf">legacy_function&lt;/span>&lt;span class="p">()&lt;/span> &lt;span class="p">{&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="kt">int&lt;/span>&lt;span class="o">*&lt;/span> &lt;span class="n">ptr&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="k">new&lt;/span> &lt;span class="kt">int&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="mi">10&lt;/span>&lt;span class="p">);&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c1">// ... कुछ प्रक्रिया ...
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">&lt;/span> &lt;span class="k">if&lt;/span> &lt;span class="p">(&lt;/span>&lt;span class="n">some_condition&lt;/span>&lt;span class="p">)&lt;/span> &lt;span class="p">{&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">return&lt;/span>&lt;span class="p">;&lt;/span> &lt;span class="c1">// मेमोरी लीक होता है! delete कॉल नहीं किया गया
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">&lt;/span> &lt;span class="p">}&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">delete&lt;/span> &lt;span class="n">ptr&lt;/span>&lt;span class="p">;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="p">}&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>ऊपर दिए गए कोड में, यदि कोई अपवाद (exception) आता है या जल्दी रिटर्न होता है, तो &lt;code>delete&lt;/code> छोड़ दिया जाता है, जिससे मेमोरी लीक होती है। इसे रोकने के लिए इस्तेमाल होने वाला प्रतिमान &amp;ldquo;RAII (Resource Acquisition Is Initialization)&amp;rdquo; है। RAII एक ऐसी तकनीक है जो संसाधन आवंटन को ऑब्जेक्ट के इनिशियलाइज़ेशन (कंस्ट्रक्टर) से और संसाधन की मुक्ति को ऑब्जेक्ट के विनाश (डिस्ट्रक्टर) से जोड़ती है। स्मार्ट पॉइंटर्स, मेमोरी प्रबंधन में इस RAII इडियम को लागू करने वाले मानक लाइब्रेरी क्लास स्टैक हैं।&lt;/p>
&lt;h2 id="2-stdunique_ptr-शनय-ओवरहड-क-सथ-वशष-सवमतव-exclusive-ownership">2. &lt;code>std::unique_ptr&lt;/code>: शून्य ओवरहेड के साथ विशेष स्वामित्व (Exclusive Ownership)
&lt;/h2>&lt;p>&lt;code>std::unique_ptr&lt;/code> एक स्मार्ट पॉइंटर है जिसका डायनामिक रूप से आवंटित ऑब्जेक्ट्स पर &amp;ldquo;विशेष स्वामित्व (Exclusive Ownership)&amp;rdquo; होता है। किसी दिए गए संसाधन का मालिक हमेशा केवल एक ही &lt;code>unique_ptr&lt;/code> हो सकता है।&lt;/p>
&lt;h3 id="21-शनय-ओवरहड-zero-overhead-क-सदधत">2.1 शून्य ओवरहेड (Zero Overhead) का सिद्धांत
&lt;/h3>&lt;p>&lt;code>std::unique_ptr&lt;/code> का सबसे बड़ा आकर्षण इसका प्रदर्शन है। कस्टम डिलीटर (deleter) के बिना डिफ़ॉल्ट स्थिति में, &lt;code>std::unique_ptr&lt;/code> का आकार कच्चे पॉइंटर (Raw Pointer) के बिल्कुल समान होता है। इसमें कोई अनावश्यक सदस्य चर (member variables) नहीं होते हैं, और वर्चुअल फ़ंक्शन का भी उपयोग नहीं किया जाता है। कंपाइलर ऑप्टिमाइज़ेशन के कारण, &lt;code>std::unique_ptr&lt;/code> के माध्यम से एक्सेस करने पर कच्चे पॉइंटर के समान असेंबली कोड उत्पन्न होता है।&lt;/p>
&lt;h3 id="22-सवमतव-क-सथनतरण-और-stdmove">2.2 स्वामित्व का स्थानांतरण और &lt;code>std::move&lt;/code>
&lt;/h3>&lt;p>विशेष स्वामित्व होने के कारण, &lt;code>std::unique_ptr&lt;/code> को कॉपी नहीं किया जा सकता (कॉपी कंस्ट्रक्टर और कॉपी असाइनमेंट ऑपरेटर &lt;code>delete&lt;/code> कर दिए गए हैं)। स्वामित्व को दूसरे &lt;code>unique_ptr&lt;/code> में स्थानांतरित करने के लिए, &lt;code>std::move&lt;/code> का उपयोग करके मूव सेमांटिक्स (Move Semantics) का उपयोग किया जाता है।&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt"> 1
&lt;/span>&lt;span class="lnt"> 2
&lt;/span>&lt;span class="lnt"> 3
&lt;/span>&lt;span class="lnt"> 4
&lt;/span>&lt;span class="lnt"> 5
&lt;/span>&lt;span class="lnt"> 6
&lt;/span>&lt;span class="lnt"> 7
&lt;/span>&lt;span class="lnt"> 8
&lt;/span>&lt;span class="lnt"> 9
&lt;/span>&lt;span class="lnt">10
&lt;/span>&lt;span class="lnt">11
&lt;/span>&lt;span class="lnt">12
&lt;/span>&lt;span class="lnt">13
&lt;/span>&lt;span class="lnt">14
&lt;/span>&lt;span class="lnt">15
&lt;/span>&lt;span class="lnt">16
&lt;/span>&lt;span class="lnt">17
&lt;/span>&lt;span class="lnt">18
&lt;/span>&lt;span class="lnt">19
&lt;/span>&lt;span class="lnt">20
&lt;/span>&lt;span class="lnt">21
&lt;/span>&lt;span class="lnt">22
&lt;/span>&lt;span class="lnt">23
&lt;/span>&lt;span class="lnt">24
&lt;/span>&lt;span class="lnt">25
&lt;/span>&lt;span class="lnt">26
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-cpp" data-lang="cpp">&lt;span class="line">&lt;span class="cl">&lt;span class="cp">#include&lt;/span> &lt;span class="cpf">&amp;lt;iostream&amp;gt;&lt;/span>&lt;span class="cp">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="cp">#include&lt;/span> &lt;span class="cpf">&amp;lt;memory&amp;gt;&lt;/span>&lt;span class="cp">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="cp">&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="k">class&lt;/span> &lt;span class="nc">Resource&lt;/span> &lt;span class="p">{&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="k">public&lt;/span>&lt;span class="o">:&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">Resource&lt;/span>&lt;span class="p">()&lt;/span> &lt;span class="p">{&lt;/span> &lt;span class="n">std&lt;/span>&lt;span class="o">::&lt;/span>&lt;span class="n">cout&lt;/span> &lt;span class="o">&amp;lt;&amp;lt;&lt;/span> &lt;span class="s">&amp;#34;Resource acquired&lt;/span>&lt;span class="se">\n&lt;/span>&lt;span class="s">&amp;#34;&lt;/span>&lt;span class="p">;&lt;/span> &lt;span class="p">}&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="o">~&lt;/span>&lt;span class="n">Resource&lt;/span>&lt;span class="p">()&lt;/span> &lt;span class="p">{&lt;/span> &lt;span class="n">std&lt;/span>&lt;span class="o">::&lt;/span>&lt;span class="n">cout&lt;/span> &lt;span class="o">&amp;lt;&amp;lt;&lt;/span> &lt;span class="s">&amp;#34;Resource destroyed&lt;/span>&lt;span class="se">\n&lt;/span>&lt;span class="s">&amp;#34;&lt;/span>&lt;span class="p">;&lt;/span> &lt;span class="p">}&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="kt">void&lt;/span> &lt;span class="nf">do_something&lt;/span>&lt;span class="p">()&lt;/span> &lt;span class="p">{&lt;/span> &lt;span class="n">std&lt;/span>&lt;span class="o">::&lt;/span>&lt;span class="n">cout&lt;/span> &lt;span class="o">&amp;lt;&amp;lt;&lt;/span> &lt;span class="s">&amp;#34;Doing something&lt;/span>&lt;span class="se">\n&lt;/span>&lt;span class="s">&amp;#34;&lt;/span>&lt;span class="p">;&lt;/span> &lt;span class="p">}&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="p">};&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="kt">void&lt;/span> &lt;span class="nf">process_resource&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">std&lt;/span>&lt;span class="o">::&lt;/span>&lt;span class="n">unique_ptr&lt;/span>&lt;span class="o">&amp;lt;&lt;/span>&lt;span class="n">Resource&lt;/span>&lt;span class="o">&amp;gt;&lt;/span> &lt;span class="n">ptr&lt;/span>&lt;span class="p">)&lt;/span> &lt;span class="p">{&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">ptr&lt;/span>&lt;span class="o">-&amp;gt;&lt;/span>&lt;span class="n">do_something&lt;/span>&lt;span class="p">();&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c1">// स्कोप से बाहर निकलने पर ptr नष्ट हो जाता है, और Resource भी मुक्त हो जाता है
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">&lt;/span>&lt;span class="p">}&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="kt">int&lt;/span> &lt;span class="nf">main&lt;/span>&lt;span class="p">()&lt;/span> &lt;span class="p">{&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">std&lt;/span>&lt;span class="o">::&lt;/span>&lt;span class="n">unique_ptr&lt;/span>&lt;span class="o">&amp;lt;&lt;/span>&lt;span class="n">Resource&lt;/span>&lt;span class="o">&amp;gt;&lt;/span> &lt;span class="n">my_ptr&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">std&lt;/span>&lt;span class="o">::&lt;/span>&lt;span class="n">make_unique&lt;/span>&lt;span class="o">&amp;lt;&lt;/span>&lt;span class="n">Resource&lt;/span>&lt;span class="o">&amp;gt;&lt;/span>&lt;span class="p">();&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c1">// process_resource(my_ptr); // त्रुटि: कॉपी नहीं किया जा सकता
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">&lt;/span> &lt;span class="n">process_resource&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">std&lt;/span>&lt;span class="o">::&lt;/span>&lt;span class="n">move&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">my_ptr&lt;/span>&lt;span class="p">));&lt;/span> &lt;span class="c1">// स्वामित्व का स्थानांतरण
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">if&lt;/span> &lt;span class="p">(&lt;/span>&lt;span class="o">!&lt;/span>&lt;span class="n">my_ptr&lt;/span>&lt;span class="p">)&lt;/span> &lt;span class="p">{&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">std&lt;/span>&lt;span class="o">::&lt;/span>&lt;span class="n">cout&lt;/span> &lt;span class="o">&amp;lt;&amp;lt;&lt;/span> &lt;span class="s">&amp;#34;my_ptr is now empty.&lt;/span>&lt;span class="se">\n&lt;/span>&lt;span class="s">&amp;#34;&lt;/span>&lt;span class="p">;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="p">}&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">return&lt;/span> &lt;span class="mi">0&lt;/span>&lt;span class="p">;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="p">}&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>नीचे दिया गया Mermaid आरेख &lt;code>std::move&lt;/code> का उपयोग करके स्वामित्व के स्थानांतरण की अवधारणा को दर्शाता है।&lt;/p>
&lt;div class="mermaid">graph LR
subgraph "std::move से पहले"
A["unique_ptr (ptr1)"] -->|"स्वामित्व"| B["हीप मेमोरी (ऑब्जेक्ट)"]
end
subgraph "std::move के बाद"
C["unique_ptr (ptr1)"] -.->|"खाली (nullptr)"| D["nullptr"]
E["unique_ptr (ptr2)"] -->|"स्वामित्व"| F["हीप मेमोरी (ऑब्जेक्ट)"]
end&lt;/div>
&lt;h3 id="23-कसटम-डलटर-custom-deleter-क-करयनवयन">2.3 कस्टम डिलीटर (Custom Deleter) का कार्यान्वयन
&lt;/h3>&lt;p>C भाषा के लिगेसी API (जैसे &lt;code>FILE*&lt;/code> या सॉकेट) को रैप करते समय, मेमोरी को मुक्त करने के लिए &lt;code>delete&lt;/code> के अलावा अन्य कार्यों (जैसे &lt;code>fclose&lt;/code>) को कॉल करना आवश्यक हो सकता है। &lt;code>std::unique_ptr&lt;/code> के दूसरे टेम्प्लेट आर्गुमेंट के रूप में कस्टम डिलीटर निर्दिष्ट किया जा सकता है।&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt"> 1
&lt;/span>&lt;span class="lnt"> 2
&lt;/span>&lt;span class="lnt"> 3
&lt;/span>&lt;span class="lnt"> 4
&lt;/span>&lt;span class="lnt"> 5
&lt;/span>&lt;span class="lnt"> 6
&lt;/span>&lt;span class="lnt"> 7
&lt;/span>&lt;span class="lnt"> 8
&lt;/span>&lt;span class="lnt"> 9
&lt;/span>&lt;span class="lnt">10
&lt;/span>&lt;span class="lnt">11
&lt;/span>&lt;span class="lnt">12
&lt;/span>&lt;span class="lnt">13
&lt;/span>&lt;span class="lnt">14
&lt;/span>&lt;span class="lnt">15
&lt;/span>&lt;span class="lnt">16
&lt;/span>&lt;span class="lnt">17
&lt;/span>&lt;span class="lnt">18
&lt;/span>&lt;span class="lnt">19
&lt;/span>&lt;span class="lnt">20
&lt;/span>&lt;span class="lnt">21
&lt;/span>&lt;span class="lnt">22
&lt;/span>&lt;span class="lnt">23
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-cpp" data-lang="cpp">&lt;span class="line">&lt;span class="cl">&lt;span class="cp">#include&lt;/span> &lt;span class="cpf">&amp;lt;cstdio&amp;gt;&lt;/span>&lt;span class="cp">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="cp">#include&lt;/span> &lt;span class="cpf">&amp;lt;memory&amp;gt;&lt;/span>&lt;span class="cp">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="cp">&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">// कस्टम डिलीटर के लिए फनक्टर (Functor)
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">&lt;/span>&lt;span class="k">struct&lt;/span> &lt;span class="nc">FileDeleter&lt;/span> &lt;span class="p">{&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="kt">void&lt;/span> &lt;span class="nf">operator&lt;/span>&lt;span class="p">()(&lt;/span>&lt;span class="n">FILE&lt;/span>&lt;span class="o">*&lt;/span> &lt;span class="n">fp&lt;/span>&lt;span class="p">)&lt;/span> &lt;span class="k">const&lt;/span> &lt;span class="p">{&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">if&lt;/span> &lt;span class="p">(&lt;/span>&lt;span class="n">fp&lt;/span>&lt;span class="p">)&lt;/span> &lt;span class="p">{&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">std&lt;/span>&lt;span class="o">::&lt;/span>&lt;span class="n">cout&lt;/span> &lt;span class="o">&amp;lt;&amp;lt;&lt;/span> &lt;span class="s">&amp;#34;Closing file.&lt;/span>&lt;span class="se">\n&lt;/span>&lt;span class="s">&amp;#34;&lt;/span>&lt;span class="p">;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">std&lt;/span>&lt;span class="o">::&lt;/span>&lt;span class="n">fclose&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">fp&lt;/span>&lt;span class="p">);&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="p">}&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="p">}&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="p">};&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="k">using&lt;/span> &lt;span class="n">UniqueFile&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">std&lt;/span>&lt;span class="o">::&lt;/span>&lt;span class="n">unique_ptr&lt;/span>&lt;span class="o">&amp;lt;&lt;/span>&lt;span class="n">FILE&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">FileDeleter&lt;/span>&lt;span class="o">&amp;gt;&lt;/span>&lt;span class="p">;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="kt">int&lt;/span> &lt;span class="nf">main&lt;/span>&lt;span class="p">()&lt;/span> &lt;span class="p">{&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">UniqueFile&lt;/span> &lt;span class="n">file&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">std&lt;/span>&lt;span class="o">::&lt;/span>&lt;span class="n">fopen&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s">&amp;#34;test.txt&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="s">&amp;#34;w&amp;#34;&lt;/span>&lt;span class="p">));&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">if&lt;/span> &lt;span class="p">(&lt;/span>&lt;span class="n">file&lt;/span>&lt;span class="p">)&lt;/span> &lt;span class="p">{&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">std&lt;/span>&lt;span class="o">::&lt;/span>&lt;span class="n">fputs&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s">&amp;#34;Hello, Smart Pointers!&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">file&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="n">get&lt;/span>&lt;span class="p">());&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="p">}&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c1">// स्कोप समाप्त होने पर FileDeleter कॉल किया जाता है और fclose हो जाता है
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">&lt;/span> &lt;span class="k">return&lt;/span> &lt;span class="mi">0&lt;/span>&lt;span class="p">;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="p">}&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>यदि कस्टम डिलीटर के रूप में फ़ंक्शन पॉइंटर या लैम्ब्डा एक्सप्रेशन का उपयोग किया जाता है, तो &lt;code>unique_ptr&lt;/code> का आकार बढ़ सकता है, लेकिन जैसा कि ऊपर दिखाया गया है, स्टेटलेस फ़ंक्शन ऑब्जेक्ट (Functor) का उपयोग करने से C++ के &lt;strong>EBCO (Empty Base Class Optimization)&lt;/strong> या C++20 के &lt;code>[[no_unique_address]]&lt;/code> के कारण इसका आकार कच्चे पॉइंटर से अधिक नहीं बढ़ता है (शून्य ओवरहेड बना रहता है)।&lt;/p>
&lt;h2 id="3-stdshared_ptr-सझ-सवमतव-shared-ownership-और-कटरल-बलक">3. &lt;code>std::shared_ptr&lt;/code>: साझा स्वामित्व (Shared Ownership) और कंट्रोल ब्लॉक
&lt;/h2>&lt;p>&lt;code>std::shared_ptr&lt;/code> एक स्मार्ट पॉइंटर है जिसका उपयोग कई पॉइंटर्स द्वारा एक ही ऑब्जेक्ट के स्वामित्व को साझा करने के लिए किया जाता है। जब अंतिम &lt;code>shared_ptr&lt;/code> नष्ट हो जाता है, तो इसके द्वारा प्रबंधित ऑब्जेक्ट मुक्त हो जाता है।&lt;/p>
&lt;h3 id="31-आतरक-आरकटकचर-कटरल-बलक">3.1 आंतरिक आर्किटेक्चर: कंट्रोल ब्लॉक
&lt;/h3>&lt;p>&lt;code>std::shared_ptr&lt;/code> प्रबंधित ऑब्जेक्ट के पॉइंटर के अलावा, हीप पर &lt;strong>कंट्रोल ब्लॉक (Control Block)&lt;/strong> नामक मेटाडेटा आवंटित करता है और उसे साझा करता है। कंट्रोल ब्लॉक में निम्नलिखित जानकारी शामिल होती है:&lt;/p>
&lt;ol>
&lt;li>&lt;strong>Strong Count (मजबूत संदर्भ गणना)&lt;/strong>: ऑब्जेक्ट का स्वामित्व रखने वाले &lt;code>shared_ptr&lt;/code> की संख्या। जब यह 0 हो जाता है, तो ऑब्जेक्ट नष्ट हो जाता है।&lt;/li>
&lt;li>&lt;strong>Weak Count (कमजोर संदर्भ गणना)&lt;/strong>: ऑब्जेक्ट की निगरानी करने वाले &lt;code>weak_ptr&lt;/code> की संख्या। जब Strong Count और Weak Count दोनों 0 हो जाते हैं, तो कंट्रोल ब्लॉक स्वयं मुक्त हो जाता है।&lt;/li>
&lt;li>&lt;strong>कस्टम डिलीटर और एलोकेटर&lt;/strong> (यदि निर्दिष्ट हो)।&lt;/li>
&lt;/ol>
&lt;div class="mermaid">graph TD
A["std::shared_ptr&lt;T> (sp1)"] -->|"T की ओर पॉइंटर"| B["प्रबंधित ऑब्जेक्ट (T)"]
A -->|"कंट्रोल ब्लॉक की ओर पॉइंटर"| C["कंट्रोल ब्लॉक"]
D["std::shared_ptr&lt;T> (sp2)"] -->|"T की ओर पॉइंटर"| B
D -->|"कंट्रोल ब्लॉक की ओर पॉइंटर"| C
C -->|"हटाता है (Deletes)"| B
C -.->|"Strong Count: 2"| E["Strong Count"]
C -.->|"Weak Count: 0"| F["Weak Count"]
C -.->|"कस्टम डिलीटर"| G["डिलीटर"]&lt;/div>
&lt;p>इस कारण से, &lt;code>std::shared_ptr&lt;/code> ऑब्जेक्ट का आकार आमतौर पर कच्चे पॉइंटर से दोगुना (ऑब्जेक्ट की ओर पॉइंटर और कंट्रोल ब्लॉक की ओर पॉइंटर) होता है।&lt;/p>
&lt;h3 id="32-परदरशन-और-एटमक-ऑपरशस-atomic-operations">3.2 प्रदर्शन और एटॉमिक ऑपरेशंस (Atomic Operations)
&lt;/h3>&lt;p>कंट्रोल ब्लॉक के भीतर संदर्भ गणना (reference count) को &lt;strong>एटॉमिक ऑपरेशंस (Atomic Operations)&lt;/strong> के रूप में लागू किया जाता है, ताकि मल्टीथ्रेडेड वातावरण में भी इसे सुरक्षित रूप से बढ़ाया या घटाया जा सके।&lt;/p>
&lt;p>x86/x64 आर्किटेक्चर में, संदर्भ गणना को बढ़ाने या घटाने के लिए &lt;code>lock xadd&lt;/code> जैसे एटॉमिक निर्देशों का उपयोग किया जाता है। इसमें सामान्य पूर्णांक जोड़ (integer addition) की तुलना में दर्जनों साइकिलों का ओवरहेड होता है। इसलिए, यदि &lt;code>shared_ptr&lt;/code> को फ़ंक्शन में मान द्वारा (by value) पास किया जाता है, तो प्रत्येक कॉपी पर एटॉमिक इंक्रीमेंट और डिक्रीमेंट होता है, जिससे प्रदर्शन में कमी आती है।&lt;/p>
&lt;p>&lt;strong>सर्वोत्तम अभ्यास (Best Practice)&lt;/strong>: &lt;code>shared_ptr&lt;/code> को फ़ंक्शन में पास करते समय, जब तक कि स्वामित्व साझा करना आवश्यक न हो, इसे &lt;code>const std::shared_ptr&amp;lt;T&amp;gt;&amp;amp;&lt;/code> (const संदर्भ) के रूप में पास करना चाहिए, या कच्चा पॉइंटर/संदर्भ (raw pointer/reference) पास करना चाहिए।&lt;/p>
&lt;h3 id="33-stdmake_shared-vs-new">3.3 &lt;code>std::make_shared&lt;/code> vs &lt;code>new&lt;/code>
&lt;/h3>&lt;p>&lt;code>shared_ptr&lt;/code> बनाते समय, जहाँ तक संभव हो &lt;code>std::make_shared&lt;/code> का उपयोग करना चाहिए। इसके दो प्रमुख कारण हैं:&lt;/p>
&lt;ol>
&lt;li>&lt;strong>मेमोरी आवंटन का अनुकूलन&lt;/strong>:
&lt;code>new&lt;/code> का उपयोग करने पर, ऑब्जेक्ट और कंट्रोल ब्लॉक के लिए हीप आवंटन (heap allocation) दो बार होता है। &lt;code>std::make_shared&lt;/code> का उपयोग करने पर, दोनों को समाहित करने वाला एक बड़ा मेमोरी ब्लॉक एक ही हीप आवंटन में सुरक्षित किया जा सकता है, जिससे कैश दक्षता (cache efficiency) भी बढ़ती है।&lt;/li>
&lt;li>&lt;strong>अपवाद सुरक्षा (Exception Safety)&lt;/strong>:
C++17 से पहले के मानकों में, फ़ंक्शन के तर्कों (arguments) के मूल्यांकन का क्रम अनिर्दिष्ट (unspecified) था, इसलिए &lt;code>new&lt;/code> द्वारा आवंटित पॉइंटर को &lt;code>shared_ptr&lt;/code> के कंस्ट्रक्टर में पास करने से पहले यदि अन्य तर्कों के मूल्यांकन के दौरान कोई अपवाद आता, तो मेमोरी लीक का जोखिम होता था। &lt;code>make_shared&lt;/code> इस समस्या से पूरी तरह बचाता है।&lt;/li>
&lt;/ol>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt">1
&lt;/span>&lt;span class="lnt">2
&lt;/span>&lt;span class="lnt">3
&lt;/span>&lt;span class="lnt">4
&lt;/span>&lt;span class="lnt">5
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-cpp" data-lang="cpp">&lt;span class="line">&lt;span class="cl">&lt;span class="c1">// बचने योग्य तरीका (2 बार मेमोरी आवंटन)
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">&lt;/span>&lt;span class="n">std&lt;/span>&lt;span class="o">::&lt;/span>&lt;span class="n">shared_ptr&lt;/span>&lt;span class="o">&amp;lt;&lt;/span>&lt;span class="n">MyClass&lt;/span>&lt;span class="o">&amp;gt;&lt;/span> &lt;span class="n">ptr1&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="k">new&lt;/span> &lt;span class="n">MyClass&lt;/span>&lt;span class="p">());&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">// अनुशंसित तरीका (1 बार मेमोरी आवंटन)
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">&lt;/span>&lt;span class="n">std&lt;/span>&lt;span class="o">::&lt;/span>&lt;span class="n">shared_ptr&lt;/span>&lt;span class="o">&amp;lt;&lt;/span>&lt;span class="n">MyClass&lt;/span>&lt;span class="o">&amp;gt;&lt;/span> &lt;span class="n">ptr2&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">std&lt;/span>&lt;span class="o">::&lt;/span>&lt;span class="n">make_shared&lt;/span>&lt;span class="o">&amp;lt;&lt;/span>&lt;span class="n">MyClass&lt;/span>&lt;span class="o">&amp;gt;&lt;/span>&lt;span class="p">();&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;h2 id="4-stdweak_ptr-सरकलर-रफरस-circular-references-क-समधन-और-नगरन">4. &lt;code>std::weak_ptr&lt;/code>: सर्कुलर रेफरेंस (Circular References) का समाधान और निगरानी
&lt;/h2>&lt;p>साझा स्वामित्व की एक बड़ी कमजोरी &amp;ldquo;सर्कुलर रेफरेंस (Circular References)&amp;rdquo; है। यदि ऑब्जेक्ट A और ऑब्जेक्ट B एक-दूसरे को &lt;code>shared_ptr&lt;/code> द्वारा इंगित कर रहे हैं, तो प्रत्येक का Strong Count कम से कम 1 पर बना रहता है, और प्रोग्राम समाप्त होने तक यह कभी 0 नहीं होता, जिससे मेमोरी लीक होती है।&lt;/p>
&lt;div class="mermaid">graph TD
subgraph "सर्कुलर रेफरेंस (Memory Leak)"
A["ऑब्जेक्ट A"] -->|"shared_ptr (Strong=1)"| B["ऑब्जेक्ट B"]
B -->|"shared_ptr (Strong=1)"| A
end&lt;/div>
&lt;h3 id="41-stdweak_ptr-दवर-चकर-cycle-क-तडन">4.1 &lt;code>std::weak_ptr&lt;/code> द्वारा चक्र (Cycle) को तोड़ना
&lt;/h3>&lt;p>इस समस्या का समाधान &lt;code>std::weak_ptr&lt;/code> है। &lt;code>weak_ptr&lt;/code> को &lt;code>shared_ptr&lt;/code> से बनाया जाता है और यह ऑब्जेक्ट को संदर्भित करता है, लेकिन &lt;strong>यह Strong Count को नहीं बढ़ाता है&lt;/strong>। इसके बजाय, यह Weak Count को बढ़ाता है। इससे स्वामित्व के बिना ऑब्जेक्ट की &amp;ldquo;निगरानी&amp;rdquo; की जा सकती है।&lt;/p>
&lt;div class="mermaid">graph TD
subgraph "सर्कुलर रेफरेंस को तोड़ना"
C["ऑब्जेक्ट A"] -->|"shared_ptr (Strong=1)"| D["ऑब्जेक्ट B"]
D -.->|"weak_ptr (Weak=1)"| C
end&lt;/div>
&lt;h3 id="42-lock-मथड-क-मधयम-स-सरकषत-एकसस">4.2 &lt;code>lock()&lt;/code> मेथड के माध्यम से सुरक्षित एक्सेस
&lt;/h3>&lt;p>&lt;code>weak_ptr&lt;/code> के पास सीधे ऑब्जेक्ट तक पहुँचने वाले ऑपरेटर (&lt;code>-&amp;gt;&lt;/code> या &lt;code>*&lt;/code>) नहीं होते हैं। ऐसा इसलिए है क्योंकि लक्षित ऑब्जेक्ट के नष्ट होने की संभावना हो सकती है। इसे सुरक्षित रूप से एक्सेस करने के लिए, &lt;code>lock()&lt;/code> मेथड को कॉल करके अस्थायी रूप से &lt;code>shared_ptr&lt;/code> प्राप्त किया जाता है।&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt"> 1
&lt;/span>&lt;span class="lnt"> 2
&lt;/span>&lt;span class="lnt"> 3
&lt;/span>&lt;span class="lnt"> 4
&lt;/span>&lt;span class="lnt"> 5
&lt;/span>&lt;span class="lnt"> 6
&lt;/span>&lt;span class="lnt"> 7
&lt;/span>&lt;span class="lnt"> 8
&lt;/span>&lt;span class="lnt"> 9
&lt;/span>&lt;span class="lnt">10
&lt;/span>&lt;span class="lnt">11
&lt;/span>&lt;span class="lnt">12
&lt;/span>&lt;span class="lnt">13
&lt;/span>&lt;span class="lnt">14
&lt;/span>&lt;span class="lnt">15
&lt;/span>&lt;span class="lnt">16
&lt;/span>&lt;span class="lnt">17
&lt;/span>&lt;span class="lnt">18
&lt;/span>&lt;span class="lnt">19
&lt;/span>&lt;span class="lnt">20
&lt;/span>&lt;span class="lnt">21
&lt;/span>&lt;span class="lnt">22
&lt;/span>&lt;span class="lnt">23
&lt;/span>&lt;span class="lnt">24
&lt;/span>&lt;span class="lnt">25
&lt;/span>&lt;span class="lnt">26
&lt;/span>&lt;span class="lnt">27
&lt;/span>&lt;span class="lnt">28
&lt;/span>&lt;span class="lnt">29
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-cpp" data-lang="cpp">&lt;span class="line">&lt;span class="cl">&lt;span class="cp">#include&lt;/span> &lt;span class="cpf">&amp;lt;iostream&amp;gt;&lt;/span>&lt;span class="cp">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="cp">#include&lt;/span> &lt;span class="cpf">&amp;lt;memory&amp;gt;&lt;/span>&lt;span class="cp">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="cp">&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="k">class&lt;/span> &lt;span class="nc">Node&lt;/span> &lt;span class="p">{&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="k">public&lt;/span>&lt;span class="o">:&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">std&lt;/span>&lt;span class="o">::&lt;/span>&lt;span class="n">string&lt;/span> &lt;span class="n">name&lt;/span>&lt;span class="p">;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">std&lt;/span>&lt;span class="o">::&lt;/span>&lt;span class="n">shared_ptr&lt;/span>&lt;span class="o">&amp;lt;&lt;/span>&lt;span class="n">Node&lt;/span>&lt;span class="o">&amp;gt;&lt;/span> &lt;span class="n">next&lt;/span>&lt;span class="p">;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">std&lt;/span>&lt;span class="o">::&lt;/span>&lt;span class="n">weak_ptr&lt;/span>&lt;span class="o">&amp;lt;&lt;/span>&lt;span class="n">Node&lt;/span>&lt;span class="o">&amp;gt;&lt;/span> &lt;span class="n">prev&lt;/span>&lt;span class="p">;&lt;/span> &lt;span class="c1">// सर्कुलर रेफरेंस को रोकने के लिए weak_ptr का उपयोग
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">Node&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="k">const&lt;/span> &lt;span class="n">std&lt;/span>&lt;span class="o">::&lt;/span>&lt;span class="n">string&lt;/span>&lt;span class="o">&amp;amp;&lt;/span> &lt;span class="n">n&lt;/span>&lt;span class="p">)&lt;/span> &lt;span class="o">:&lt;/span> &lt;span class="n">name&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">n&lt;/span>&lt;span class="p">)&lt;/span> &lt;span class="p">{&lt;/span> &lt;span class="n">std&lt;/span>&lt;span class="o">::&lt;/span>&lt;span class="n">cout&lt;/span> &lt;span class="o">&amp;lt;&amp;lt;&lt;/span> &lt;span class="s">&amp;#34;Created &amp;#34;&lt;/span> &lt;span class="o">&amp;lt;&amp;lt;&lt;/span> &lt;span class="n">name&lt;/span> &lt;span class="o">&amp;lt;&amp;lt;&lt;/span> &lt;span class="s">&amp;#34;&lt;/span>&lt;span class="se">\n&lt;/span>&lt;span class="s">&amp;#34;&lt;/span>&lt;span class="p">;&lt;/span> &lt;span class="p">}&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="o">~&lt;/span>&lt;span class="n">Node&lt;/span>&lt;span class="p">()&lt;/span> &lt;span class="p">{&lt;/span> &lt;span class="n">std&lt;/span>&lt;span class="o">::&lt;/span>&lt;span class="n">cout&lt;/span> &lt;span class="o">&amp;lt;&amp;lt;&lt;/span> &lt;span class="s">&amp;#34;Destroyed &amp;#34;&lt;/span> &lt;span class="o">&amp;lt;&amp;lt;&lt;/span> &lt;span class="n">name&lt;/span> &lt;span class="o">&amp;lt;&amp;lt;&lt;/span> &lt;span class="s">&amp;#34;&lt;/span>&lt;span class="se">\n&lt;/span>&lt;span class="s">&amp;#34;&lt;/span>&lt;span class="p">;&lt;/span> &lt;span class="p">}&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="p">};&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="kt">int&lt;/span> &lt;span class="nf">main&lt;/span>&lt;span class="p">()&lt;/span> &lt;span class="p">{&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">auto&lt;/span> &lt;span class="n">nodeA&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">std&lt;/span>&lt;span class="o">::&lt;/span>&lt;span class="n">make_shared&lt;/span>&lt;span class="o">&amp;lt;&lt;/span>&lt;span class="n">Node&lt;/span>&lt;span class="o">&amp;gt;&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s">&amp;#34;A&amp;#34;&lt;/span>&lt;span class="p">);&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">auto&lt;/span> &lt;span class="n">nodeB&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">std&lt;/span>&lt;span class="o">::&lt;/span>&lt;span class="n">make_shared&lt;/span>&lt;span class="o">&amp;lt;&lt;/span>&lt;span class="n">Node&lt;/span>&lt;span class="o">&amp;gt;&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s">&amp;#34;B&amp;#34;&lt;/span>&lt;span class="p">);&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">nodeA&lt;/span>&lt;span class="o">-&amp;gt;&lt;/span>&lt;span class="n">next&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">nodeB&lt;/span>&lt;span class="p">;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">nodeB&lt;/span>&lt;span class="o">-&amp;gt;&lt;/span>&lt;span class="n">prev&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">nodeA&lt;/span>&lt;span class="p">;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c1">// weak_ptr से shared_ptr प्राप्त करके एक्सेस करना
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">&lt;/span> &lt;span class="k">if&lt;/span> &lt;span class="p">(&lt;/span>&lt;span class="k">auto&lt;/span> &lt;span class="n">locked_prev&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">nodeB&lt;/span>&lt;span class="o">-&amp;gt;&lt;/span>&lt;span class="n">prev&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="n">lock&lt;/span>&lt;span class="p">())&lt;/span> &lt;span class="p">{&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">std&lt;/span>&lt;span class="o">::&lt;/span>&lt;span class="n">cout&lt;/span> &lt;span class="o">&amp;lt;&amp;lt;&lt;/span> &lt;span class="s">&amp;#34;Node B&amp;#39;s prev is &amp;#34;&lt;/span> &lt;span class="o">&amp;lt;&amp;lt;&lt;/span> &lt;span class="n">locked_prev&lt;/span>&lt;span class="o">-&amp;gt;&lt;/span>&lt;span class="n">name&lt;/span> &lt;span class="o">&amp;lt;&amp;lt;&lt;/span> &lt;span class="s">&amp;#34;&lt;/span>&lt;span class="se">\n&lt;/span>&lt;span class="s">&amp;#34;&lt;/span>&lt;span class="p">;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="p">}&lt;/span> &lt;span class="k">else&lt;/span> &lt;span class="p">{&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">std&lt;/span>&lt;span class="o">::&lt;/span>&lt;span class="n">cout&lt;/span> &lt;span class="o">&amp;lt;&amp;lt;&lt;/span> &lt;span class="s">&amp;#34;Node B&amp;#39;s prev is already destroyed.&lt;/span>&lt;span class="se">\n&lt;/span>&lt;span class="s">&amp;#34;&lt;/span>&lt;span class="p">;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="p">}&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">return&lt;/span> &lt;span class="mi">0&lt;/span>&lt;span class="p">;&lt;/span> &lt;span class="c1">// nodeA और nodeB उचित रूप से नष्ट हो जाएंगे
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">&lt;/span>&lt;span class="p">}&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;h2 id="5-मलटथरडड-वतवरण-म-सझ-सवमतव-क-समए">5. मल्टीथ्रेडेड वातावरण में साझा स्वामित्व की सीमाएँ
&lt;/h2>&lt;p>&lt;code>shared_ptr&lt;/code> की थ्रेड-सुरक्षा (thread safety) के बारे में अक्सर गलतफहमी होती है। &amp;ldquo;कंट्रोल ब्लॉक में संदर्भ गणना (reference count) का अपडेट थ्रेड-सेफ होता है&amp;rdquo;, लेकिन &amp;ldquo;&lt;code>shared_ptr&lt;/code> ऑब्जेक्ट को स्वयं पढ़ना या लिखना थ्रेड-सेफ नहीं होता है&amp;rdquo;।&lt;/p>
&lt;ul>
&lt;li>&lt;strong>सुरक्षित संचालन&lt;/strong>: कई थ्रेड्स, &lt;em>अपने स्वयं के&lt;/em> &lt;code>shared_ptr&lt;/code> इंस्टेंस (जो समान कंट्रोल ब्लॉक साझा करते हैं) को पढ़ते या लिखते हैं।&lt;/li>
&lt;li>&lt;strong>डेटा रेस (खतरा)&lt;/strong>: कई थ्रेड्स, &lt;em>बिल्कुल एक ही&lt;/em> &lt;code>shared_ptr&lt;/code> इंस्टेंस पर एक साथ पढ़ते या लिखते हैं।&lt;/li>
&lt;/ul>
&lt;p>यदि एक ही इंस्टेंस को कई थ्रेड्स के बीच साझा करने की आवश्यकता है, तो &lt;code>std::atomic&amp;lt;std::shared_ptr&amp;lt;T&amp;gt;&amp;gt;&lt;/code> (C++20) का उपयोग किया जाना चाहिए, या इसे म्यूटेक्स (&lt;code>std::mutex&lt;/code>) के साथ सुरक्षित किया जाना चाहिए।&lt;/p>
&lt;h2 id="6-सदरभ-गणन-क-गणतय-सतरकरण">6. संदर्भ गणना का गणितीय सूत्रीकरण
&lt;/h2>&lt;p>कंट्रोल ब्लॉक में जीवनचक्र अवस्था संक्रमण (lifecycle state transition) को गणितीय रूप में निम्न प्रकार से व्यक्त किया जा सकता है:
मान लें कि समय $t$ पर Strong Count $S(t)$ है और Weak Count $W(t)$ है।&lt;/p>
&lt;p>प्रारंभिक अवस्था (&lt;code>make_shared&lt;/code> के तुरंत बाद):
&lt;/p>
$$ S(0) = 1, \quad W(0) = 0 $$
&lt;p>कॉपी (&lt;code>shared_ptr&lt;/code> का प्रतिरूपण) होने पर:
&lt;/p>
$$ S(t_{next}) = S(t) + 1 $$
&lt;p>प्रबंधित ऑब्जेक्ट (Managed Object) के नष्ट होने की स्थिति:
&lt;/p>
$$ \lim_{t \to t_d} S(t) = 0 $$
&lt;p>कंट्रोल ब्लॉक (Control Block) स्वयं के मेमोरी से मुक्त होने की स्थिति:
&lt;/p>
$$ S(t) = 0 \quad \land \quad W(t) = 0 $$
&lt;p>
अर्थात,
&lt;/p>
$$ S(t) + W(t) = 0 $$
&lt;p>जैसा कि यह सूत्र दर्शाता है, जब तक &lt;code>weak_ptr&lt;/code> मौजूद है ($W(t) > 0$), प्रबंधित ऑब्जेक्ट के नष्ट होने के बाद भी कंट्रोल ब्लॉक के लिए छोटी मेमोरी स्पेस सुरक्षित रहती है। यह &lt;code>make_shared&lt;/code> का एकमात्र नुकसान हो सकता है (चूंकि प्रबंधित ऑब्जेक्ट की मेमोरी और कंट्रोल ब्लॉक एक साथ जुड़े होते हैं, यदि कोई कमजोर संदर्भ बचा रहता है, तो प्रबंधित ऑब्जेक्ट का विशाल मेमोरी स्थान भी सिस्टम को वापस नहीं किया जाता है), लेकिन आमतौर पर &lt;code>make_shared&lt;/code> का प्रदर्शन लाभ इन कमियों से कहीं अधिक होता है।&lt;/p>
&lt;h2 id="7-नषकरष">7. निष्कर्ष
&lt;/h2>&lt;p>मॉडर्न C++ में मेमोरी प्रबंधन अब मैन्युअल रूप से &lt;code>new&lt;/code>/&lt;code>delete&lt;/code> को प्रबंधित करने का युग नहीं है।&lt;/p>
&lt;ol>
&lt;li>डिफ़ॉल्ट रूप से हमेशा &lt;strong>&lt;code>std::unique_ptr&lt;/code>&lt;/strong> का उपयोग करें, और शून्य ओवरहेड का लाभ उठाते हुए स्पष्ट स्वामित्व को डिज़ाइन में शामिल करें।&lt;/li>
&lt;li>केवल तभी &lt;strong>&lt;code>std::shared_ptr&lt;/code>&lt;/strong> का उपयोग करें जब आपको वास्तव में कई मालिकों के बीच जीवनचक्र साझा करने की आवश्यकता हो, और इसे बनाने के लिए &lt;code>std::make_shared&lt;/code> का उपयोग करें।&lt;/li>
&lt;li>डेटा संरचनाओं या ऑब्जर्वर पैटर्न को लागू करने में जहां साझा करने का चक्र (सर्कुलर रेफरेंस) उत्पन्न हो सकता है, वहां मेमोरी लीक को रोकने के लिए &lt;strong>&lt;code>std::weak_ptr&lt;/code>&lt;/strong> का लाभ उठाएं।&lt;/li>
&lt;/ol>
&lt;p>स्मार्ट पॉइंटर्स को गहराई से समझने और उनका उचित स्थान पर उपयोग करने से, C++ के प्रदर्शन से समझौता किए बिना, सुरक्षित और मजबूत सॉफ्टवेयर आर्किटेक्चर का निर्माण संभव हो जाता है。&lt;/p></description></item></channel></rss>