C++ में समवर्तीता और मल्टीथ्रेडिंग: A से Z तक

शुरुआती लोगों के लिए ऑनलाइन Python प्रशिक्षक

Python आसानी से सीखें बिना सिद्धांत के बोझ के। स्वचालित जांच के साथ व्यावहारिक कार्य हल करें और ब्राउज़र में सीधे कोड लिखें।

पाठ्यक्रम शुरू करें

C++ में समवर्तीता और मल्टीथ्रेडिंग का परिचय

\n\n

आधुनिक प्रोसेसर में कई कोर होते हैं, और उनकी पूरी शक्ति का उपयोग करने के लिए, प्रोग्राम को एक साथ कई कार्य करने में सक्षम होना चाहिए। समवर्तीता (concurrency) एक प्रोग्राम की ओवरलैपिंग समय अवधि में कई कार्यों को निष्पादित करने की क्षमता है, और मल्टीथ्रेडिंग (multithreading) इसे लागू करने का एक तरीका है, जिसमें प्रोग्राम समानांतर रूप से काम करने वाले कई थ्रेड्स में विभाजित होता है।

\n\n

C++ में, मल्टीथ्रेडिंग के लिए समर्थन C++11 मानक में दिखाई दिया और तब से सक्रिय रूप से विकसित हो रहा है। इस लेख में, हम थ्रेड बनाने से लेकर जटिल सिंक्रोनाइज़ेशन पैटर्न तक सभी प्रमुख पहलुओं को कवर करेंगे।

\n\n

मूल बातें: थ्रेड बनाना और प्रबंधित करना

\n\n

std::thread — बुनियादी बिल्डिंग ब्लॉक

\n\n

क्लास std::thread आपको एक अलग थ्रेड में एक फ़ंक्शन या कॉल करने योग्य ऑब्जेक्ट चलाने की अनुमति देता है। आइए सबसे सरल उदाहरण देखें:

\n\n
#include <iostream>\n#include <thread>\n\nvoid hello() {\n    std::cout << "थ्रेड से नमस्ते " \n              << std::this_thread::get_id() << std::endl;\n}\n\nint main() {\n    std::thread t(hello);   // थ्रेड शुरू करें\n    t.join();               // थ्रेड के समाप्त होने की प्रतीक्षा करें\n    return 0;\n}
\n\n

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

\n\n

तर्क पास करना और लैम्ब्डा फ़ंक्शन

\n\n

थ्रेड्स को तर्क पास किए जा सकते हैं और लैम्ब्डा का उपयोग किया जा सकता है:

\n\n
#include <thread>\n#include <string>\n\nvoid process(int id, const std::string& data) {\n    // डेटा प्रोसेसिंग\n}\n\nint main() {\n    std::thread t1(process, 1, "डेटा");\n    std::thread t2([](int x) {\n        // लैम्ब्डा एक्सप्रेशन\n    }, 42);\n    \n    t1.join();\n    t2.join();\n}
\n\n

थ्रेड सिंक्रोनाइज़ेशन: साझा डेटा की सुरक्षा

\n\n

जब कई थ्रेड एक ही डेटा तक पहुँचते हैं, तो रेस कंडीशन (race condition) उत्पन्न होती है। इसे रोकने के लिए सिंक्रोनाइज़ेशन तंत्र का उपयोग किया जाता है।

\n\n

म्यूटेक्स (std::mutex)

\n\n

म्यूटेक्स एक सिंक्रोनाइज़ेशन प्रिमिटिव है जो गारंटी देता है कि किसी भी समय केवल एक थ्रेड ही इसका मालिक हो सकता है:

\n\n
#include <iostream>\n#include <thread>\n#include <mutex>\n\nstd::mutex mtx;\nint counter = 0;\n\nvoid increment() {\n    for (int i = 0; i < 100000; ++i) {\n        std::lock_guard<std::mutex> lock(mtx);\n        ++counter;  // संरक्षित पहुँच\n    }\n}\n\nint main() {\n    std::thread t1(increment);\n    std::thread t2(increment);\n    \n    t1.join();\n    t2.join();\n    \n    std::cout << "काउंटर: " << counter << std::endl;\n    return 0;\n}
\n\n

std::lock_guard एक RAII रैपर है जो बनने पर स्वचालित रूप से म्यूटेक्स को लॉक करता है और नष्ट होने पर अनलॉक करता है। यह गलती से म्यूटेक्स को छोड़ना भूल जाने से बचाता है।

\n\n

कंडीशन वेरिएबल (std::condition_variable)

\n\n

कंडीशन वेरिएबल थ्रेड्स को किसी विशिष्ट घटना के होने की प्रतीक्षा करने की अनुमति देते हैं:

\n\n
#include <queue>\n#include <condition_variable>\n\nstd::queue<int> data_queue;\nstd::mutex queue_mutex;\nstd::condition_variable cv;\n\nvoid producer() {\n    for (int i = 0; i < 10; ++i) {\n        std::this_thread::sleep_for(std::chrono::milliseconds(100));\n        std::lock_guard<std::mutex> lock(queue_mutex);\n        data_queue.push(i);\n        cv.notify_one();  // उपभोक्ता को सूचित करें\n    }\n}\n\nvoid consumer() {\n    while (true) {\n        std::unique_lock<std::mutex> lock(queue_mutex);\n        cv.wait(lock, []{ return !data_queue.empty(); });\n        \n        int value = data_queue.front();\n        data_queue.pop();\n        lock.unlock();\n        \n        // प्रोसेस                

ब्लॉग

पुस्तक अनुशंसाएँ