स्थिति जो मैं वर्णन करूंगा वह एक आईपैड 4 (एआरएमवी 7 एस) पर हो रहा है, जो म्यूटेक्स लॉक/अनलॉक पर पॉज़िक्स libs का उपयोग कर रहा है। मैंने अन्य एआरएमवी 7 उपकरणों पर समान चीजें देखी हैं, हालांकि (नीचे देखें), इसलिए मुझे लगता है कि किसी भी समाधान के लिए एआरएमवी 7 के लिए म्यूटेक्स और मेमोरी बाड़ के व्यवहार पर अधिक सामान्य रूप की आवश्यकता होगी।क्या mutex_unlock मेमोरी बाड़ के रूप में कार्य करता है?
void ProduceFunction() {
MutexLock();
int TempProducerIndex = mSharedProducerIndex; // Take a copy of the int member variable for Producers Index
mSharedArray[TempProducerIndex++] = NewData; // Copy new Data into array at Temp Index
mSharedProducerIndex = TempProducerIndex; // Signal consumer data is ready by assigning new Producer Index to shared variable
MutexUnlock();
}
थ्रेड 2 - उपभोक्ता डेटा:
void ConsumingFunction() {
while (mConsumerIndex != mSharedProducerIndex) {
doWorkOnData (mSharedArray[mConsumerIndex++]);
}
}
पहले (जब समस्या क्रॉप - उत्पादन डाटा
थ्रेड 1:
छद्म परिदृश्य के लिए कोड आईपैड 2 पर), मुझे विश्वास था कि mSharedProducerIndex = TempProducerIndex
परफ नहीं किया जा रहा था परमाणु रूप से ormedically, और इसलिए का उपयोग mSharedProducerIndex
असाइन करने के लिए बदल गया। इस बिंदु तक यह काम कर चुका है, लेकिन यह पता चला कि मैं गलत था और बग वापस आ गया है। मुझे लगता है कि 'फिक्स' बस कुछ समय बदल गया।
मैं अब निष्कर्ष यह है कि वास्तविक समस्या म्युटेक्स लॉक, यानी भीतर लेखन के आदेश निष्पादन के बाहर है अगर या तो संकलक या हार्डवेयर को पुन: व्यवस्थित करने का निर्णय लिया के लिए आए हैं:
mSharedArray[TempProducerIndex++] = NewData; // Copy new Data into array at Temp Index
mSharedProducerIndex = TempProducerIndex; // Signal consumer data is ready by assigning new Producer Index to shared variable
.. । के लिए:
mSharedProducerIndex = TempProducerIndex; // Signal consumer data is ready by assigning new Producer Index to shared variable
mSharedArray[TempProducerIndex++] = NewData; // Copy new Data into array at Temp Index
... और फिर उपभोक्ता निर्माता interleaved, डेटा अभी तक नहीं लिखा है | किया गया जब उपभोक्ता इसे पढ़ने की कोशिश की।
स्मृति बाधाओं पर कुछ पढ़ने के बाद, मैं इसलिए सोचा कि मैं करने के लिए लिखा गया था mutex_unlock
बाहर उपभोक्ता के लिए संकेत ले जाने का प्रयास करना चाहते हैं, उनका मानना है कि अनलॉक एक स्मृति बाधा/बाड़ जो mSharedArray
यह सुनिश्चित करना होगा उत्पादन होगा:
mSharedArray[TempProducerIndex++] = NewData; // Copy new Data into array at Temp Index
MutexUnlock();
mSharedProducerIndex = TempProducerIndex; // Signal consumer data is ready by assigning new Producer Index to shared variable
हालांकि, यह अभी भी विफल रहता है, और मुझे प्रश्न पूछता है कि mutex_unlock
निश्चित रूप से एक लिखने की बाड़ के रूप में कार्य करेगा या नहीं?
मैं भी an article from HP पढ़ा है जो सुझाव दिया है कि compilers (लेकिन बाहर के) crit_sec
रों में कोड को स्थानांतरित कर सकते हैं। तो उपरोक्त परिवर्तन के बाद भी, mSharedProducerIndex
का लेखन बाधा से पहले हो सकता है। क्या इस सिद्धांत के लिए कोई लाभ है?
एक स्पष्ट बाड़ को जोड़ कर समस्या दूर हो जाने:
mSharedArray[TempProducerIndex++] = NewData; // Copy new Data into array at Temp Index
OSMemoryBarrier();
mSharedProducerIndex = TempProducerIndex; // Signal consumer data is ready by assigning new Producer Index to shared variable
इसलिए मैं लगता है कि मैं इस समस्या को समझने, और कहा कि एक बाड़ आवश्यक है, लेकिन अनलॉक के व्यवहार में किसी भी अंतर्दृष्टि और कारण है कि यह 'नहीं करता है एक बाधा प्रदर्शन करने के लिए प्रतीत होता है वास्तव में उपयोगी होगा।
संपादित करें:
उपभोक्ता सूत्र में एक म्युटेक्स की कमी के बारे में: मैं उम्मीद कर रहा उपभोक्ता या तो नए या पुराने मूल्य पढ़ें एक एकल अनुदेश जा रहा है int mSharedProducerIndex
के लिखने पर भरोसा कर रहा हूँ और इसलिए । या तो मान्य राज्य हैं, और mSharedArray
प्रदान करना अनुक्रम में लिखा गया है (यानी।mSharedProducerIndex
लिखने से पहले) यह ठीक रहेगा, लेकिन अब तक जो कहा गया है, उससे मैं इसका जवाब नहीं दे सकता।
यही तर्क ऐसा लगता है कि वर्तमान बाधा समाधान भी त्रुटिपूर्ण के रूप में mSharedProducerIndex
लिखने बाधा के अंदर ले जाया जा सकता है और इसलिए संभवतः गलत तरीके से फिर से आदेश दिया जा सकता है के द्वारा।
क्या यह केवल पढ़ने के लिए बाधा के रूप में कार्य करने के लिए उपभोक्ता को म्यूटेक्स जोड़ने की सिफारिश की जाती है, या क्या pragma
या पीपीसी पर EIEIO
जैसे निर्माता पर आउट ऑफ़ ऑर्डर निष्पादन को अक्षम करने के लिए निर्देश है?
स्टीव सुझाव के अनुसार, आप * पढ़ने * * mSharedProducerIndex' के तुरंत बाद OSMemoryBarrier() कर सकते हैं। पिछले परीक्षण से पता चला है कि OSMemoryBarrier() OSSpinLockLock + अनलॉक() से कुछ हद तक तेज था जो pthread mutexes से बहुत तेज था। –