2009-12-28 14 views
5

कल एक प्रश्न के बारे में दोगुना-चेक लॉकिंग ने विचारों की एक श्रृंखला शुरू की जिसने मुझे एक साधारण स्थिति के बारे में अनिश्चित छोड़ दिया। निम्न कोड में, क्या "सिंक में अब नहीं" के printf को हिट करना संभव है? इस सरल उदाहरण में, मान एक ही कैश लाइन पर होंगे, इसलिए मुझे लगता है कि यह कम संभावना होगी (संभावना है कि 0% से शुरू होने की संभावना है)।क्या WaitForSingleObject मेमोरी बैरियर के रूप में सेवा करता है?

यदि उत्तर है, "नहीं, यह संभव नहीं है।", तो मेरा अनुवर्ती प्रश्न, बल्कि अनुमानित रूप से है: क्यों नहीं? जब तक मैंने अपने विचारों को कल बहु-थ्रेडिंग धुरी के चारों ओर घिरा और लपेट लिया, तब तक मुझे लगता है कि कोड सुरक्षित होगा। लेकिन अब मैं सोच रहा हूं कि pa या pb चर के लिए कैश से पढ़ा जाने वाला एक स्टेल क्या रोकता है। और इससे कोई फर्क नहीं पड़ता कि pa, pb ने malloc'd स्मृति की बजाय सरल वैश्विक पूर्णांक चर की ओर इशारा किया है? क्या WaitForSingleObject कॉल मेमोरी बाधा प्रदान करता है? या पॉइंटर्स अस्थिर घोषित किया जाना चाहिए? इतने सारे प्रश्न, बहुत कम वाक्यों।

अद्यतन: मैं अंत में स्थित जानकारी विशेष रूप से कहा गया है कि कि कार्यों कि तुल्यकालन वस्तुओं संकेत का उपयोग करते हैं memory barriers। यह स्पष्ट होना चाहिए था, लेकिन मुझे एक निश्चित जवाब खोजने में परेशानी हो रही थी। तो मैं एक बार फिर खुद को विश्वास में डाल सकता हूं कि मैं इसे सब समझता हूं।

int i1 = 0; 
int i2 = 0; 
int reads = 0; 
int done = 0; 
int *pa = NULL; 
int *pb = NULL; 
HANDLE hSync = NULL; 

DWORD WriteThread(LPVOID pvParam) 
{ 
    while(!done) 
     { 
     WaitForSingleObject(hSync, INFINITE); 
     (*pa)++; 
     (*pb)++; 
     ReleaseSemaphore(hSync, 1, NULL); 
     } 
    return 0; 
} 

DWORD ReadThread(LPVOID pvParam) 
{ 
    while(!done) 
     { 
     WaitForSingleObject(hSync, INFINITE); 
     if (*pa != *pb) 
     { 
     printf("No longer in sync: %d, %d\n", *pa, *pb); 
     exit(1); 
     } 
     ReleaseSemaphore(hSync, 1, NULL); 
     reads++; 
     } 
    return 0; 
} 

int main(int argc, char* argv[]) 
{ 
    DWORD dwID; 

    // malloc'd memory 
    pa = (int*)malloc(sizeof(int)); 
    pb = (int*)malloc(sizeof(int)); 

    // Is a simple global variable different? 
    //pa = &i1; 
    //pb = &i2; 

    *pa = 0; 
    *pb = 0; 

    hSync = CreateSemaphore(NULL, 1, 1, NULL); 
    CreateThread(NULL, 0, WriteThread, NULL, 0, &dwID); 
    CreateThread(NULL, 0, ReadThread, NULL, 0, &dwID); 

    while (*pa < 1000000) 
     Sleep(1); 
    done = 1; 

    return 0; 
} 

उत्तर

4

यह कोई फर्क नहीं पड़ता, जहां स्मृति निहित है, और अगर यह कैश जुटना के बारे में सभी थे, तो चर अस्थिर इसे ठीक करने के लिए कुछ भी नहीं करना होगा की घोषणा की। अस्थिरता के अर्थशास्त्र न तो आवश्यक हैं और न ही थ्रेड-सुरक्षा के लिए पर्याप्त हैं; इसका इस्तेमाल न करें!

सी/सी ++ स्तर पर, पीए और पीबी को रजिस्टरों में कैश किया जा सकता है, लेकिन उन्हें किसी फंक्शन कॉल के बाद बासी माना जाएगा। सीपीयू स्तर पर, सभी प्रतीक्षा फ़ंक्शन बाधाओं का उपयोग करते हैं ताकि यह सुनिश्चित किया जा सके कि सब कुछ अपेक्षित काम करता है।

+0

+1 ठीक वही जो मैं कहने जा रहा था। – tony

+0

जानकारी के लिए धन्यवाद। क्या आपको एक लिंक पता है जो प्रतीक्षा कार्यों और स्मृति बाधाओं पर चर्चा करता है। यही वह है जिसे मैं ढूंढ रहा था और इसे नहीं देखा। यह काफी संभव है कि मैं सिर्फ अंधा हूं और कुछ स्पष्ट याद किया। –

+2

आप अंधे नहीं हैं; प्रासंगिक जानकारी ऑनलाइन खोजना मुश्किल है। एमएसडीएन http://msdn.microsoft.com/en-us/library/ms686355%28VS.85%29.aspx पर एक उचित रूप से अच्छा अवलोकन प्रदान करता है। –

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