boost::shared_mutex
या std::shared_mutex
(सी ++ 17) एकल लेखक, एकाधिक पाठक पहुंच के लिए उपयोग किया जा सकता है। एक शैक्षणिक अभ्यास के रूप में, मैंने एक सरल कार्यान्वयन किया जो स्पिनलॉकिंग का उपयोग करता है और इसमें अन्य सीमाएं हैं (उदाहरण के लिए निष्पक्षता नीति), लेकिन स्पष्ट रूप से वास्तविक अनुप्रयोगों में उपयोग करने का इरादा नहीं है।सी ++ shared_mutex कार्यान्वयन
विचार यह है कि म्यूटेक्स एक संदर्भ गणना रखता है जो शून्य नहीं है अगर कोई थ्रेड लॉक नहीं रखता है। यदि> 0, मान उन पाठकों की संख्या का प्रतिनिधित्व करता है जिनके पास पहुंच है। यदि -1, एक लेखक के पास पहुंच है।
क्या यह सही कार्यान्वयन है (विशेष रूप से उपयोग किए गए, न्यूनतम, मेमोरी ऑर्डरिंग के साथ) जो डेटा दौड़ से मुक्त है?
#include <atomic>
class my_shared_mutex {
std::atomic<int> refcount{0};
public:
void lock() // write lock
{
int val;
do {
val = 0; // Can only take a write lock when refcount == 0
} while (!refcount.compare_exchange_weak(val, -1, std::memory_order_acquire));
// can memory_order_relaxed be used if only a single thread takes write locks ?
}
void unlock() // write unlock
{
refcount.store(0, std::memory_order_release);
}
void lock_shared() // read lock
{
int val;
do {
do {
val = refcount.load(std::memory_order_relaxed);
} while (val == -1); // spinning until the write lock is released
} while (!refcount.compare_exchange_weak(val, val+1, std::memory_order_acquire));
}
void unlock_shared() // read unlock
{
refcount.fetch_sub(1, std::memory_order_relaxed);
}
};
मुझे अनलॉक_श्रेड में मेमोरी ऑर्डर के बारे में निश्चित नहीं था, लेकिन मेरा तर्क यह था कि यह वास्तव में कुछ भी 'रिलीज़' नहीं करता है क्योंकि इसमें केवल पढ़ने के लिए पहुंच है और – LWimsey
@LWimsey की सुरक्षा वाले डेटा को नहीं बदला जा सकता है: हाँ, यह कठिन है स्टोर ऑर्डरिंग से लोड ऑर्डरिंग के बारे में सोचने के लिए, लेकिन यह एक असली बात है। इस समय एक लोड वैश्विक रूप से दिखाई देता है जब यह एल 1 कैश से डेटा पढ़ता है। (क्योंकि वह तब होता है जब यह एक ही सीपीयू के आउट-ऑफ-ऑर्डर कोर में वैश्विक रूप से सुसंगत कैश से एक प्रतिलिपि बनाता है।) –