क्या यह संगामिति के लिए सुरक्षित है। संगोष्ठी :: समवर्ती_वेक्टर :: पुश_बैक जबकि अन्य सूत्र में उस समवर्ती_वीर से अधिक पुनरावृत्ति?


9

push_back , शुरू , अंत में समवर्ती सुरक्षित रूप में वर्णित हैं https://docs.microsoft.com/en-us/cpp/parallel/concrt/reference/concurrent-vector-class?view=vs-2019#push_back

हालाँकि नीचे का कोड मुखर है। संभवतः क्योंकि तत्व जोड़ा गया है लेकिन अभी तक इनिशियलाइज़ नहीं किया गया है।

struct MyData
   {
   explicit MyData()
      {
      memset(arr, 0xA5, sizeof arr);
      }
   std::uint8_t arr[1024];
   };

struct MyVec
   {
   concurrency::concurrent_vector<MyData> v;
   };

auto vector_pushback(MyVec &vec) -> void
   {
   vec.v.push_back(MyData{});
   }

auto vector_loop(MyVec &vec) -> void
   {
   MyData myData;
   for (auto it = vec.v.begin(); it != vec.v.end(); ++it)
      {
      auto res = memcmp(&(it->arr), &(myData.arr), sizeof myData.arr);
      assert(res == 0);
      }
   }

int main()
{
   auto vec = MyVec{};
   auto th_vec = std::vector<std::thread>{};
   for (int i = 0; i < 1000; ++i)
      {
      th_vec.emplace_back(vector_pushback, std::ref(vec));
      th_vec.emplace_back(vector_loop, std::ref(vec));
      }

   for(auto &th : th_vec)
      th.join();

    return 0;
}

जवाबों:


2

डॉक्स के अनुसार , उस concurrency::concurrent_vectorपर पुनरावृति करते समय इसे जोड़ना सुरक्षित होना चाहिए क्योंकि तत्वों को वास्तव में मेमोरी में संचित रूप से संग्रहीत नहीं किया जाता है std::vector:

concurrent_vectorजब आप इसे कहते हैं या इसका आकार बदलते हैं तो कोई वस्तु अपने तत्वों को स्थानांतरित नहीं करती है। यह समवर्ती बिंदुओं और पुनरावृत्तियों को समवर्ती संचालन के दौरान वैध बने रहने में सक्षम बनाता है।

हालाँकि, push_backVS2017 के वास्तविक कार्यान्वयन को देखते हुए, मैं निम्नलिखित देखता हूं, जो मुझे नहीं लगता कि थ्रेड-सुरक्षित है:

iterator push_back( _Ty &&_Item )
{
    size_type _K;
    void *_Ptr = _Internal_push_back(sizeof(_Ty), _K);
    new (_Ptr) _Ty( std::move(_Item));
    return iterator(*this, _K, _Ptr);
}

मुझे _Internal_push_backयहाँ पर अटकलें लगानी हैं, लेकिन मैं इसे दांव लगाना चाहूँगा कि यह आइटम को संग्रहीत करने के लिए कच्ची मेमोरी आवंटित करें (और इस नए नोड की ओर अंतिम तत्व को इंगित करता है) ताकि अगली पंक्ति विस्थापन का नया उपयोग कर सके। मुझे लगता है कि _Internal_push_backआंतरिक रूप से थ्रेड-सुरक्षित है, हालांकि मुझे विस्थापन नए से पहले कोई सिंक्रनाइज़ेशन नहीं होता है। मतलब निम्नलिखित संभव है:

  • स्मृति प्राप्त की जाती है और नोड "प्रेजेंट" होता है (फिर भी विस्थापन नया नहीं है)
  • लूपिंग थ्रेड इस नोड का सामना करता है memcmpऔर पता चलता है कि वे समान नहीं हैं
  • विस्थापन नया होता है।

यहाँ निश्चित रूप से एक दौड़ की स्थिति है। मैं अनायास समस्या को पुन: उत्पन्न कर सकता हूं, अधिक धागे का उपयोग करता हूं।

मेरा सुझाव है कि आप इस पर Microsoft समर्थन के साथ एक टिकट खोलें।



1
MSFT अद्यतन प्रलेखन github.com/MicrosoftDocs/cpp-docs/commit/…
pidgun
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.