2013-07-27 2 views
0

여러 스레드가 공통 컨테이너 (예 : 맵)에 쓸 수있는 방법에 대해 조언 해 줄 수 있기를 바랬습니다. Boost와 C++을 사용하여 일부 스레드가 동일한 키를 공유하는 시나리오여러 스레드가 쓰기를 수행합니까?

map은 std :: map 유형 일 수 있습니다. 다른 데이터 멤버를 수정하기 위해 객체에 액세스하는 다른 스레드가있을 수 있습니다. 계속 진행하기 전에 각 스레드가 현재 스레드에 대한 unique_lock을 마칠 때까지 기다릴까요?

는이 예로서 임계 영역 진입 각 스레드처럼 간단 할 것 : 사전

+1

[std :: map'] (http://en.cppreference.com/w/cpp/container/map)은 일반적으로 ** 해시 ** 맵이 아니지만 [std :: unordered_map '] (http://en.cppreference.com/w/cpp/container/unordered_map)입니다. 귀하의 답변에 대해 –

답변

2

당신은 데이터 구조의 스레드 안전 구현을 만들어야에서

//somewhere within the code 
boost::unique_lock mutex; 

void modifyMap(const std::string& key,const unsigned int dataX, 
       const unsigned int dataY) 
{ 
    // would each thread wait for exclusive access? 
    boost::unique_lock<boost::shared_mutex> lock (mutex); 

    // i now have exclusive access no race conditions; 
    m_map.find(key)->second.setDataX(dataX); 
    m_map.find(key)->second.setDataX(dataY); 
} 

감사합니다. 잠금 기반 (예 : 뮤텍스를 사용하여 구현 됨) 또는 잠금이 필요하지 않음 (C++ 11 및 부스트에서 지원되는 원자 연산 또는 메모리 순서 지정 사용) 일 수 있습니다.

잠금 기반 접근 방식에 대해 간략하게 설명 할 수 있습니다. 예를 들어, 스레드 안전 링크드 목록을 디자인 할 수 있습니다. 스레드가 읽기 조작 만 수행하면 모든 것이 안전합니다. 반면에이 데이터 구조에 쓰려고하면 목록에서 이전 노드와 다음 노드 포인터가 필요할 수 있습니다 (삽입 된 노드를 가리 키도록 포인터를 업데이트해야하는 경우 이중 링크 됨). 다른 스레드는 잘못된 포인터 데이터를 읽을 수 있으므로 새 노드를 삽입하려는 두 노드에 대한 잠금이 필요합니다. 이것은 직렬화를 생성하고 (다른 스레드는 뮤텍스가 잠금 해제 될 때까지 대기합니다) 동시성의 가능성을 줄입니다.

조회 테이블의 전체 예제는 Anthony Williams의 "C++ Concurrency : Practical Multithreading"책의 171 페이지, 6.11에 있습니다. 이 책의 저자는 boost :: thread 및 C++ 11 스레드 라이브러리를 모두 설계하여 최신 C++ 표준을 사용하는 멀티 스레딩 프로그래밍을 시작하기에 적합합니다.

업데이트 : 예를 들어 읽기/쓰기 작업을 수행하려면 (더 많은 작업이 필요하다면 보호해야합니다) boost :: shared_mutex를 사용하는 것이 더 낫습니다. 기본적으로 다중 읽기 단일 쓰기 액세스가 허용됩니다. 스레드가 독점 잠금을 획득하고 다른 모든 스레드가 대기해야하는 것보다 쓰기를 원합니다. 다음은 몇 가지 코드입니다.

template <typename mapType> 
class threadSafeMap { 

boost::shared_mutex map_mutex; 
mapType* m_map; 

public: 

threadSafeMap() { 
    m_map = new mapType(); 
} 


void modifyMap(std::string& key,const unsigned int dataX, 
       const unsigned int dataY) 
{ 
    //std::lock_guard in c++11. std::shared_mutex is going to be available in C++14 
    //acquire exclusive access - other threads wait 
    boost::lock_guard<boost::shared_mutex> lck(map_mutex); 

    m_map.find(key)->second.setDataX(dataX); 
    m_map.find(key)->second.setDataX(dataY); 
} 


int getValueByKey(std::string& key) 
{ 
    //std::lock_guard in c++11. std::shared_mutex is going to be available in C++11 
    //acquire shared access - other threads can read. If the other thread needs access it has to wait for a fully unlocked state. 
    boost::shared_lock<boost::shared_mutex> lck(map_mutex); 

    return m_map.getValue(key); 
} 


~threadSafeMap() { 
    delete m_map; 
} 


}; 

잠금 가드 객체가 삭제되고 수명이 끝날 때 뮤텍스가 잠금 해제됩니다. mapType 템플릿은지도 유형으로 대체 될 수 있습니다.

+0

주셔서 감사합니다. 간단히 말해서 위의 함수에 액세스하는 여러 스레드가 독점 액세스가있는 스레드가 종료 될 때까지 차단되는지 여부를 알고 싶습니다 (다음 스레드가 맵 수정을 진행할 때까지). 이것은 내가 찾고있는 행동입니다 – godzilla

+0

몇 가지 코드를 추가했습니다. 쓰기에는 boost :: shared_mutex, boost :: lock_guard, 읽기에는 boost :: shared_lock을 사용해야합니다. 필요한 경우 다른 작업도 동일한 방식으로 수정해야합니다. –

+0

대단히 고맙습니다. 많은 질문을 명확히하는 데 도움이됩니다. 고유 한 잠금으로 업그레이드해도 작동합니까? – godzilla

관련 문제