2016-02-07 12 views
8

मैं अपने प्रोजेक्ट में एक बिंदु पर पहुंच गया हूं जिसके लिए उन संसाधनों पर धागे के बीच संचार की आवश्यकता है जो बहुत अच्छी तरह से लिखे जा सकते हैं, इसलिए सिंक्रनाइज़ेशन जरूरी है। हालांकि मैं मूल स्तर के अलावा किसी अन्य चीज़ पर सिंक्रनाइज़ेशन को वास्तव में समझ नहीं पा रहा हूं।std :: lock_guard उदाहरण, यह क्यों काम करता है

इस लिंक में पिछले उदाहरण पर विचार करें: http://www.bogotobogo.com/cplusplus/C11/7_C11_Thread_Sharing_Memory.php

#include <iostream> 
#include <thread> 
#include <list> 
#include <algorithm> 
#include <mutex> 

using namespace std; 

// a global variable 
std::list<int>myList; 

// a global instance of std::mutex to protect global variable 
std::mutex myMutex; 

void addToList(int max, int interval) 
{ 
    // the access to this function is mutually exclusive 
    std::lock_guard<std::mutex> guard(myMutex); 
    for (int i = 0; i < max; i++) { 
     if((i % interval) == 0) myList.push_back(i); 
    } 
} 

void printList() 
{ 
    // the access to this function is mutually exclusive 
    std::lock_guard<std::mutex> guard(myMutex); 
    for (auto itr = myList.begin(), end_itr = myList.end(); itr != end_itr; ++itr) { 
     cout << *itr << ","; 
    } 
} 

int main() 
{ 
    int max = 100; 

    std::thread t1(addToList, max, 1); 
    std::thread t2(addToList, max, 10); 
    std::thread t3(printList); 

    t1.join(); 
    t2.join(); 
    t3.join(); 

    return 0; 
} 

उदाहरण दर्शाता है कि कैसे तीन सूत्र, दो लेखकों और एक पाठक, एक साझा संसाधन (सूची) तक पहुँचता है।

दो वैश्विक कार्यों का उपयोग किया जाता है: एक जिसे दो लेखक धागे द्वारा उपयोग किया जाता है, और पाठक धागे द्वारा उपयोग किया जा रहा है। दोनों कार्य एक ही संसाधन, सूची को लॉक करने के लिए लॉक_गार्ड का उपयोग करते हैं।

अब यह है कि मैं अपने सिर को चारों ओर लपेट नहीं सकता हूं: पाठक दो लेखक धागे की तुलना में एक अलग दायरे में लॉक का उपयोग करता है, फिर भी एक ही संसाधन को बंद कर देता है। यह कैसे काम कर सकता है? म्यूटेक्स की मेरी सीमित समझ लेखक समारोह में अच्छी तरह से उधार देती है, वहां आपको सटीक एक ही फ़ंक्शन का उपयोग करके दो धागे मिलते हैं। मैं समझ सकता हूं कि, एक चेक सही है क्योंकि आप संरक्षित क्षेत्र में प्रवेश करने वाले हैं, और यदि कोई और पहले से ही अंदर है, तो आप प्रतीक्षा करें।

लेकिन जब दायरा अलग है? यह इंगित करेगा कि प्रक्रिया के मुकाबले कुछ प्रकार का तंत्र अधिक शक्तिशाली है, कुछ प्रकार के रनटाइम पर्यावरण "देर से" थ्रेड के निष्पादन को अवरुद्ध कर रहा है। लेकिन मैंने सोचा कि सी ++ में ऐसी कोई चीज नहीं थी। तो मैं एक नुकसान में हूँ।

यहां हुड के नीचे क्या चल रहा है?

+1

मैं जोड़ना चाहता हूं कि म्यूटेक्स लॉकिंग [परमाणु] (http://stackoverflow.com/questions/15054086/what-does-atomic-mean-in-programming)। उम्मीद है की यह मदद करेगा। – Incomputable

उत्तर

3

myMutex वैश्विक है, जिसका उपयोग myList की सुरक्षा के लिए किया जाता है। guard(myMutex) बस लॉक को संलग्न करता है और ब्लॉक से बाहर निकलने से इसका विनाश होता है, ताला लगा देता है। guard लॉक को संलग्न करने और संलग्न करने का एक सुविधाजनक तरीका है।

इस तरह से, mutex किसी भी डेटा की सुरक्षा नहीं करता है। यह डेटा की सुरक्षा के लिए प्रदान करता है। यह डिज़ाइन पैटर्न है जो डेटा की सुरक्षा करता है। इसलिए यदि मैं नीचे सूचीबद्ध सूची को संशोधित करने के लिए अपना स्वयं का फ़ंक्शन लिखता हूं, तो mutex इसकी रक्षा नहीं कर सकता है।

void addToListUnsafe(int max, int interval) 
{ 
    for (int i = 0; i < max; i++) { 
     if((i % interval) == 0) myList.push_back(i); 
    } 
} 

ताला तभी काम करता है कोड के सभी टुकड़ों है कि डेटा का उपयोग करने की जरूरत है ऐक्सेस करने से पहले ताला लगे रहते हैं और उसके बाद वे किया जाता है छुड़ाना। प्रत्येक एक्सेस से पहले और बाद में लॉक को आकर्षक और डिस्प्ले करने का यह डिज़ाइन-पैटर्न डेटा की सुरक्षा करता है (myList आपके मामले में)

अब आप सोचेंगे, mutex का उपयोग क्यों करें, और क्यों नहीं, कहें bool। और हाँ आप कर सकते हैं, लेकिन आपको यह सुनिश्चित करना होगा कि bool वैरिएबल कुछ विशेषताओं को प्रदर्शित करेगा, लेकिन नीचे दी गई सूची तक सीमित नहीं है।

  1. एकाधिक धागे में कैश (अस्थिर) नहीं किया जा सकता है।
  2. पढ़ें और लिखना परमाणु ऑपरेशन होगा।
  3. आपका लॉक स्थिति को संभाल सकता है जहां कई निष्पादन पाइपलाइन (तार्किक कोर, आदि) हैं।

, अलग synchronization तंत्र है कि "धीमे प्रदर्शन" की लागत से (सूत्र, बनाम बहु प्रोसेसर, एकल प्रोसेसर, आदि भर बनाम प्रक्रियाओं में) "बेहतर ताला" प्रदान करते हैं ताकि आप हमेशा एक ताला तंत्र का चयन करना चाहिए जो आपकी स्थिति के लिए पर्याप्त है।

2

यह ठीक है कि लॉक करता है। जब कोई थ्रेड लॉक लेता है, इस पर ध्यान दिए बिना कि कोड में ऐसा कहां है, तो उसे किसी अन्य थ्रेड को लॉक रखने पर इसकी बारी का इंतजार करना होगा। जब कोई थ्रेड लॉक जारी करता है, इस पर ध्यान दिए बिना कि कोड में ऐसा कहां है, तो दूसरा धागा उस लॉक को प्राप्त कर सकता है।

ताले डेटा की रक्षा करते हैं, कोड नहीं। वे सुरक्षित कोड तक पहुंचने वाले सभी कोड को सुनिश्चित करते हुए ऐसा करते हैं, जबकि यह से अन्य थ्रेड को छोड़कर, कोड से अन्य थ्रेड को छोड़कर, उसी डेटा तक पहुंच सकता है।

8

के प्रासंगिक लाइन पर एक नजर है:

std::lock_guard<std::mutex> guard(myMutex); 

सूचना है कि lock_guard संदर्भ वैश्विक म्युटेक्स myMutex। यही है, सभी तीन धागे के लिए एक ही म्यूटेक्स। क्या lock_guard करता है अनिवार्य रूप से यह है:

  • निर्माण पर, यह myMutex ताले और इसे करने के लिए एक संदर्भ रहता है।
  • विनाश पर (यानी जब गार्ड का दायरा छोड़ा जाता है), तो यह myMutex को अनलॉक करता है।

म्यूटेक्स हमेशा एक ही है, इसका दायरा से कोई लेना देना नहीं है। lock_guard का बिंदु सिर्फ आपके लिए म्यूटेक्स को लॉक करना और अनलॉक करना है। उदाहरण के लिए, यदि आप मैन्युअल रूप से lock/unlock पर हैं, लेकिन आपका फ़ंक्शन मध्य में कहीं अपवाद फेंकता है, तो यह कभी भी unlock कथन तक नहीं पहुंच पाएगा। तो, इसे मैन्युअल तरीके से कर रहे हैं आप यह सुनिश्चित करना है कि म्यूटेक्स हमेशा अनलॉक हो।दूसरी तरफ, lock_guard ऑब्जेक्ट स्वचालित रूप से नष्ट हो जाता है जब भी कार्य समाप्त हो जाता है - भले ही यह कैसे निकलता है।

+1

आप सही हैं, लेकिन मुझे डर है कि मुझे गलत समझा गया है। मेरा वास्तव में क्या मतलब है कि यह निम्न स्तर पर कैसे काम करता है। डेटा का एक टुकड़ा बस कुछ स्मृति सेट है। यदि आप उस डेटा की रक्षा करना चाहते हैं, तो आपको इसे समाहित करना होगा। यह यहां काम पर ऐसा कुछ नहीं प्रतीत होता है, आप आसानी से एक साधारण int को आसानी से बंद कर सकते हैं। तो लॉक वास्तव में लागू किए जाने वाले संरक्षण तंत्र को कैसे लागू किया जाता है? चूंकि गुंजाइश अप्रासंगिक है, इसलिए संसाधन को मुक्त होने के बाद कुछ और देर से थ्रेड को छेड़छाड़ करना, इसे बंद करना और इसे फिर से जागृत करना चाहिए। मुझे मिलना? – Deviatore

+0

@ डेवियतोर: इसे ऑपरेटिंग सिस्टम शेड्यूलर – MikeMB

+0

कहा जाता है यह वास्तव में encapsulation के बारे में नहीं है। म्यूटेक्स अनिवार्य रूप से एक संसाधन है जिसे आप 'लॉक()' कहा जाता है जब आप प्राप्त करते हैं। अगर संसाधन प्राप्त नहीं किया जा सकता है (क्योंकि एक और धागा इसे पकड़ रहा है), जो होता है ठोस कार्यान्वयन पर निर्भर करता है; या तो [आपसी बहिष्करण एल्गोरिदम] (https://en.wikipedia.org/wiki/Mutual_exclusion#Enforcing_mutual_exclusion) का उपयोग किया जाता है, या ऑपरेटिंग सिस्टम इसे संभालता है, अपने थ्रेड को प्रतीक्षा कतार में डालता है (उदाहरण के लिए देखें [पॉज़िक्स थ्रेड पर ट्यूटोरियल प्रोग्रामिंग] (https://computing.llnl.gov/tutorials/pthreads/#Mutexes) कैसे यूनिक्स/लिनक्स सिस्टम इसे करते हैं)। – mindriot

संबंधित मुद्दे