다른 스레드에서 동시 _ 벡터를 반복하면서 동시성 : : concurrent_vector : : push_back을 호출하는 것이 동시성 안전합니까?


9

push_back , begin , endhttps://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 VS2017 보면 스레드 안전하다고 생각하지 않는 다음을 볼 수 있습니다.

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
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.