অন্য থ্রেডে সেই একত্রে_ভেক্টরটি পুনরুক্ত করার সময় কনক্যুরঞ্জি :: সমবর্তী_ভেক্টর :: পুশ_ব্যাক কল করা কি একযোগে-নিরাপদ?


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_backভিএস ২০১7- এর প্রকৃত বাস্তবায়নটি দেখে আমি নিম্নলিখিতগুলি দেখছি, যা আমি থ্রেড-নিরাপদ বলে মনে করি না:

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তারা সমান নয় বলে আবিষ্কার করে
  • এমপ্লিটমেন্ট নতুন ঘটে।

এখানে অবশ্যই রেসের শর্ত রয়েছে। আমি স্বতঃস্ফূর্তভাবে সমস্যাটি পুনরুত্পাদন করতে পারি, তত বেশি থ্রেড ব্যবহার করি।

আমি আপনাকে পরামর্শ দিচ্ছি যে আপনি এইটিতে মাইক্রোসফ্ট সমর্থন সহ একটি টিকিট খুলুন।


1
প্রতিবেদন করা হয়েছে developercommune.visualstudio.com/content/problem/822481/…
পিডগুন

1
এমএসএফটি আপডেট করেছে ডকুমেন্টেশন github.com/Mic MicrosoftDocs
cpp-
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.