खोज…


परिचय

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

संसाधन अधिग्रहण प्रारंभिक है

संसाधन अधिग्रहण प्रारंभिक है (RAII) संसाधन प्रबंधन में एक सामान्य मुहावरा है। गतिशील मेमोरी के मामले में, यह संसाधन प्रबंधन को पूरा करने के लिए स्मार्ट पॉइंटर्स का उपयोग करता है। RAII का उपयोग करते समय, अधिग्रहीत संसाधन को तुरंत स्मार्ट पॉइंटर या समकक्ष संसाधन प्रबंधक को स्वामित्व दिया जाता है। संसाधन केवल इस प्रबंधक के माध्यम से पहुँचा जाता है, इसलिए प्रबंधक विभिन्न परिचालनों पर नज़र रख सकता है। उदाहरण के लिए, std::auto_ptr अपने संबंधित संसाधन को स्वत: मुक्त कर देता है जब वह दायरे से बाहर हो जाता है या अन्यथा हटा दिया जाता है।

#include <memory>
#include <iostream>
using namespace std;

int main() {
    {
        auto_ptr ap(new int(5)); // dynamic memory is the resource
        cout << *ap << endl; // prints 5
    } // auto_ptr is destroyed, its resource is automatically freed
}
सी ++ 11

std::auto_ptr की मुख्य समस्या यह है कि इसे स्वामित्व को स्थानांतरित किए बिना कॉपी नहीं किया जा सकता है:

#include <memory>
#include <iostream>
using namespace std;

int main() {
    auto_ptr ap1(new int(5));
    cout << *ap1 << endl; // prints 5
    auto_ptr ap2(ap1); // copy ap2 from ap1; ownership now transfers to ap2
    cout << *ap2 << endl; // prints 5
    cout << ap1 == nullptr << endl; // prints 1; ap1 has lost ownership of resource
}

इन अजीब कॉपी शब्दार्थों के कारण, std::auto_ptr अन्य चीजों के अलावा कंटेनरों में उपयोग नहीं किया जा सकता है। ऐसा करने का कारण यह है कि मेमोरी को दो बार हटाने से रोका जाए: यदि एक ही संसाधन के स्वामित्व वाले दो auto_ptrs हैं, तो वे नष्ट होने पर दोनों इसे मुक्त करने का प्रयास करते हैं। पहले से मुक्त संसाधन को मुक्त करना आम तौर पर समस्याएं पैदा कर सकता है, इसलिए इसे रोकना महत्वपूर्ण है। हालाँकि, जब प्रतिलिपि करने पर स्वामित्व स्थानांतरित नहीं किया जाता है, तो std::shared_ptr में इससे बचने की एक विधि होती है:

#include <memory>
#include <iostream>
using namespace std;

int main() {
    shared_ptr sp2;
    {
        shared_ptr sp1(new int(5)); // give ownership to sp1
        cout << *sp1 << endl; // prints 5
        sp2 = sp1; // copy sp2 from sp1; both have ownership of resource
        cout << *sp1 << endl; // prints 5
        cout << *sp2 << endl; // prints 5
    } // sp1 goes out of scope and is destroyed; sp2 has sole ownership of resource
    cout << *sp2 << endl;        
} // sp2 goes out of scope; nothing has ownership, so resource is freed

म्यूटेक्स और थ्रेड सेफ्टी

समस्याएँ तब हो सकती हैं जब कई सूत्र किसी संसाधन तक पहुँचने का प्रयास करते हैं। एक सरल उदाहरण के लिए, मान लें कि हमारे पास एक धागा है जो एक चर में जोड़ता है। यह चर को पहले पढ़कर, उसमें से एक को जोड़कर, फिर उसे वापस संग्रहीत करके करता है। मान लें कि हम इस चर को 1 से शुरू करते हैं, तो इस धागे के दो उदाहरण बनाएं। दोनों सूत्र समाप्त होने के बाद, अंतर्ज्ञान से पता चलता है कि इस चर का मान 3. होना चाहिए। हालांकि, नीचे दी गई तालिका में बताया गया है कि क्या गलत हो सकता है:

धागा 1 धागा २
समय चरण 1 1 चर से पढ़ें
समय चरण 2 1 चर से पढ़ें
समय चरण 3 2 प्राप्त करने के लिए 1 प्लस 1 जोड़ें
समय चरण 4 2 प्राप्त करने के लिए 1 प्लस 1 जोड़ें
समय चरण 5 चर में स्टोर 2
समय चरण 6 चर में स्टोर 2

जैसा कि आप देख सकते हैं, ऑपरेशन के अंत में, 2 चर में है, इसके बजाय 3। इसका कारण यह है कि थ्रेड 2 ने चर 1 को पढ़ने से पहले इसे अद्यतन किया गया था। समाधान? Mutexes।

एक म्युटेक्स (mut UAL पूर्व clusion के सूटकेस) इस प्रकार की समस्या को हल करने के लिए डिज़ाइन किया गया एक संसाधन प्रबंधन वस्तु है। जब कोई थ्रेड किसी संसाधन तक पहुँच प्राप्त करना चाहता है, तो यह संसाधन के म्यूटेक्स को "प्राप्त" करता है। एक बार यह संसाधन तक पहुँचने के बाद, थ्रेड "म्यूटेक्स" को रिलीज़ करता है। जबकि म्यूटेक्स को अधिग्रहीत किया जाता है, म्यूटेक्स को अधिग्रहित करने के लिए सभी कॉल तब तक वापस नहीं आएगी जब तक म्यूटेक्स जारी नहीं किया जाता है। इसे समझने के लिए सुपरमार्केट में वेटिंग लाइन के रूप में म्यूटेक्स के बारे में सोचें: थ्रेड्स म्यूटेक्स को प्राप्त करने की कोशिश करके लाइन में जाते हैं और फिर थ्रेड्स के आगे उनके खत्म होने का इंतजार करते हैं, फिर रिसोर्स का उपयोग करते हुए, फिर बाहर निकलते हुए। म्यूटेक्स जारी करके लाइन। हर कोई एक बार में संसाधन तक पहुंचने का प्रयास करेगा तो पूरा महामारी होगा।

सी ++ 11

std::mutex C ++ 11 का म्यूटेक्स का कार्यान्वयन है।

#include <thread>
#include <mutex>
#include <iostream>
using namespace std;

void add_1(int& i, const mutex& m) { // function to be run in thread
    m.lock();
    i += 1;
    m.unlock();
}

int main() {
    int var = 1;
    mutex m;

    cout << var << endl; // prints 1
    
    thread t1(add_1, var, m); // create thread with arguments
    thread t2(add_1, var, m); // create another thread
    t1.join(); t2.join(); // wait for both threads to finish
    
    cout << var << endl; // prints 3
}


Modified text is an extract of the original Stack Overflow Documentation
के तहत लाइसेंस प्राप्त है CC BY-SA 3.0
से संबद्ध नहीं है Stack Overflow