2016-09-23 5 views
3

예제 코드.std :: unique_ptr의 STL 컨테이너에서 find()의 스레드 안전성

class Obj 
{ 
    public: 
    void doSome(void) 
    { 
     std::cout << "Hello World!" << std::endl; 
    } 
}; 

std::unordered_map<int, std::unique_ptr<Obj>> map; 

// insert -- done with single thread and before find() 
map[123] = std::move(std::unique_ptr<Obj>(new Obj)); 

// find -- run from multiple threads 
auto search = map.find(123); // <=== (Q) 
if (search != map.end())  
{ 
    search->second->doSome(); 
} 

(Q)

어떻게 스레드 추구한다에 대한 //을 실행하는 여러 스레드가 map.find (123) 섹션을 찾을 수있는 경우?

map.find (123) 항상 모든 스레드에서 OBJ을 찾을 것인가? 검색 -> 보조이 다른 사람에게 할당되지 않은 한?

+1

참고 : 함수에서 반환 한 값 (변수 이름이없는 것)은 이동하지 마십시오. 그것은 쓸모가 없다. –

+2

일반적인 규칙은 non-const 함수도 동시에 호출되지 않는 한 표준 라이브러리 클래스의'const' 멤버 함수 (예 : find')를 호출하는 것이 좋습니다. –

답변

0

find()도 아니고 정렬되지 않은지도의 다른 방법도 스레드로부터 안전하지 않습니다. 하나의 실행 스레드가 find()을 호출 할 수있는 경우 다른 스레드가이를 수정하는 정렬되지 않은 맵 메서드를 호출하면 정의되지 않은 동작이 발생합니다.

여러 실행 스레드가 동일한 키를 사용하여 find()을 호출하는 경우 정의되지 않은 동작이없는 경우 모든 실행 스레드가 해당 키에 대해 동일한 값을 갖게됩니다.

+1

정답. 읽기가 까다 롭습니다. –

1

하나 이상의 스레드가 동일한 변수에 액세스하고 그 중 하나 이상이 일 때에 데이터 경주가 있습니다. 모든 사용자가 동일한 데이터를 읽는 경우가 여기에 해당하지 않습니다. 괜찮아. 그러나이 코드에서는 다루지 않는 또 다른 문제가 있습니다. 데이터가 맵 객체에 언제 저장되는지에 따라 일부 스레드는 맵 객체의 업데이트 된 버전을 보지 못할 수 있습니다. 이 동기화 문제를 처리하는 가장 간단한 방법은 리더 스레드를 만들기 전에 맵 객체를 설정하는 것입니다.

+0

답안의 두 번째 부분에 관해서 : 다른 스레드가 이미 읽었을지도 모르는 동안에 만 맵 개체가 설정되었을 때 데이터 경주가 아닌가? –

+0

@ChristianHackl - 예, 데이터 경주에는 잠재적으로 동시 읽기 및 쓰기가 포함됩니다. 제 대답의 두 번째 부분은 데이터 경주가 아니라 변화의 가시성에 관한 것입니다. 예를 들어지도가 하나의 스레드에 의해 생성 된 경우 해당 스레드가 실행 된 프로세서 캐시에 변경 결과가있을 수 있으며 다른 프로세서에서 실행중인 다른 스레드에는 캐시 된 이전 값이 캐시되어 표시되지 않을 수 있습니다 업데이트. 새로 생성 된 쓰레드는 쓰레드가 생성 한 모든 글로벌 변경 사항을 항상 볼 수 있습니다. 따라서 맵이 초기화 될 때까지 쓰레드를 생성하지 않으면 문제가 해결됩니다. –

관련 문제