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
}
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 के सूटकेस) इस प्रकार की समस्या को हल करने के लिए डिज़ाइन किया गया एक संसाधन प्रबंधन वस्तु है। जब कोई थ्रेड किसी संसाधन तक पहुँच प्राप्त करना चाहता है, तो यह संसाधन के म्यूटेक्स को "प्राप्त" करता है। एक बार यह संसाधन तक पहुँचने के बाद, थ्रेड "म्यूटेक्स" को रिलीज़ करता है। जबकि म्यूटेक्स को अधिग्रहीत किया जाता है, म्यूटेक्स को अधिग्रहित करने के लिए सभी कॉल तब तक वापस नहीं आएगी जब तक म्यूटेक्स जारी नहीं किया जाता है। इसे समझने के लिए सुपरमार्केट में वेटिंग लाइन के रूप में म्यूटेक्स के बारे में सोचें: थ्रेड्स म्यूटेक्स को प्राप्त करने की कोशिश करके लाइन में जाते हैं और फिर थ्रेड्स के आगे उनके खत्म होने का इंतजार करते हैं, फिर रिसोर्स का उपयोग करते हुए, फिर बाहर निकलते हुए। म्यूटेक्स जारी करके लाइन। हर कोई एक बार में संसाधन तक पहुंचने का प्रयास करेगा तो पूरा महामारी होगा।
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
}