C++
सूत्र सिंक्रनाइज़ेशन संरचनाएँ
खोज…
परिचय
यदि थ्रेड्स इंटरैक्ट करते हैं, तो थ्रेड्स के साथ काम करना कुछ सिंक्रोनाइज़ेशन तकनीकों की आवश्यकता हो सकती है। इस विषय में, आप इन मुद्दों को हल करने के लिए मानक पुस्तकालय द्वारा प्रदान किए गए विभिन्न संरचनाओं को पा सकते हैं।
std :: shared_lock
कई पाठकों और अनन्य लेखकों को अनुमति देने के लिए एक साझा लॉक के साथ एक अद्वितीय लॉक के साथ साझा किया जा सकता है।
#include <unordered_map>
#include <mutex>
#include <shared_mutex>
#include <thread>
#include <string>
#include <iostream>
class PhoneBook {
public:
string getPhoneNo( const std::string & name )
{
shared_lock<shared_timed_mutex> r(_protect);
auto it = _phonebook.find( name );
if ( it == _phonebook.end() )
return (*it).second;
return "";
}
void addPhoneNo ( const std::string & name, const std::string & phone )
{
unique_lock<shared_timed_mutex> w(_protect);
_phonebook[name] = phone;
}
shared_timed_mutex _protect;
unordered_map<string,string> _phonebook;
};
std :: call_once, std :: एक बार_फ्लैग
std::call_once
किसी कार्य को std::call_once
द्वारा ठीक एक बार निष्पादित std::call_once
सुनिश्चित करता है। यह std::system_error
फेंकता है अगर यह अपना कार्य पूरा नहीं कर पाता है।
एस td::once_flag
के साथ संयोजन के रूप में प्रयोग किया जाता है td::once_flag
।
#include <mutex>
#include <iostream>
std::once_flag flag;
void do_something(){
std::call_once(flag, [](){std::cout << "Happens once" << std::endl;});
std::cout << "Happens every time" << std::endl;
}
कुशल पहुँच के लिए ऑब्जेक्ट लॉकिंग।
जब आप इस पर कई ऑपरेशन करते हैं तो अक्सर आप पूरी वस्तु को लॉक करना चाहते हैं। उदाहरण के लिए, यदि आपको पुनरावृत्तियों का उपयोग करके ऑब्जेक्ट को जांचने या संशोधित करने की आवश्यकता है । जब भी आपको कई सदस्य कार्यों को कॉल करने की आवश्यकता होती है, तो यह आम तौर पर व्यक्तिगत सदस्य कार्यों के बजाय पूरे ऑब्जेक्ट को लॉक करने के लिए अधिक कुशल होता है।
उदाहरण के लिए:
class text_buffer
{
// for readability/maintainability
using mutex_type = std::shared_timed_mutex;
using reading_lock = std::shared_lock<mutex_type>;
using updates_lock = std::unique_lock<mutex_type>;
public:
// This returns a scoped lock that can be shared by multiple
// readers at the same time while excluding any writers
[[nodiscard]]
reading_lock lock_for_reading() const { return reading_lock(mtx); }
// This returns a scoped lock that is exclusing to one
// writer preventing any readers
[[nodiscard]]
updates_lock lock_for_updates() { return updates_lock(mtx); }
char* data() { return buf; }
char const* data() const { return buf; }
char* begin() { return buf; }
char const* begin() const { return buf; }
char* end() { return buf + sizeof(buf); }
char const* end() const { return buf + sizeof(buf); }
std::size_t size() const { return sizeof(buf); }
private:
char buf[1024];
mutable mutex_type mtx; // mutable allows const objects to be locked
};
चेकसम की गणना करते समय ऑब्जेक्ट को पढ़ने के लिए लॉक कर दिया जाता है, जिससे अन्य थ्रेड्स जो ऑब्जेक्ट को उसी समय से पढ़ना चाहते हैं।
std::size_t checksum(text_buffer const& buf)
{
std::size_t sum = 0xA44944A4;
// lock the object for reading
auto lock = buf.lock_for_reading();
for(auto c: buf)
sum = (sum << 8) | (((unsigned char) ((sum & 0xFF000000) >> 24)) ^ c);
return sum;
}
ऑब्जेक्ट को साफ़ करना उसके आंतरिक डेटा को अपडेट करता है इसलिए इसे एक बहिष्करण लॉक का उपयोग करके किया जाना चाहिए।
void clear(text_buffer& buf)
{
auto lock = buf.lock_for_updates(); // exclusive lock
std::fill(std::begin(buf), std::end(buf), '\0');
}
एक से अधिक लॉक देखभाल प्राप्त करते समय हमेशा सभी थ्रेड्स के लिए एक ही क्रम में ताले प्राप्त करने के लिए लिया जाना चाहिए।
void transfer(text_buffer const& input, text_buffer& output)
{
auto lock1 = input.lock_for_reading();
auto lock2 = output.lock_for_updates();
std::copy(std::begin(input), std::end(input), std::begin(output));
}
नोट: यह सबसे अच्छा std :: deferred :: lock और कॉलिंग std :: lock का उपयोग करके किया जाता है
std :: condition_variable_any, std :: cv_status
std::condition_variable
सामान्यीकरण std::condition_variable
, std::condition_variable_any
किसी भी प्रकार की BasicLockable संरचना के साथ काम करता है।
std::cv_status
किसी स्थिति चर के लिए रिटर्न स्थिति के रूप में दो संभावित रिटर्न कोड हैं:
- std :: cv_status :: no_timeout: कोई टाइमआउट नहीं था, स्थिति चर अधिसूचित किया गया था
- std :: cv_status :: no_timeout: स्थिति चर समय समाप्त हो गया