코드에서 볼 수있는 한 가지 문제점은 특히 예외가 발생할 때 문제가 발생한다는 것입니다.
obj1->obtainMutex(); //Should I create a mutex for each object so that I could obtain mutex when I am going to update fields for obj1?
pthread_mutex_unlock(&mutexA); //release mutex for unordered_map so that other threads could access other object
obj1->field1 = 1;
performOperation(obj1);
performOperation이 예외를 throw하면 obj1-> releaseMutex(); 객체가 잠겨져 미래에 언젠가 교착 상태가 될 가능성이 있습니다. 그리고 performOperation에서 사용하는 일부 라이브러리 코드는 예외를 사용하지 않을 수도 있습니다. 또는 실수로 미래에 언젠가 실수로 리턴을 삽입하고 전에 모든 소유 잠금을 해제하는 것을 잊지 마십시오.
pthread_mutex_lock 및 pthread_mutex_unlock 호출도 마찬가지입니다.
잠금/잠금 해제에 RAII를 사용하는 것이 좋습니다.
e.e. 코드는 다음과 같을 수 있습니다.
typedef std::unordered_map<string, classA*>MAP1;
MAP1 map1;
Lock mapLock(&mutexA); //automatci variable. The destructor of the Lock class
//automatically calls pthread_mutex_unlock in its destructor if it "owns" the
//mutex
if(map1.find(id) == map1.end())
{
classA* obj1 = new classA;
map1[id] = obj1;
Lock objLock(obj);
mapLock.release(); //we explicitly release mapLock here
obj1->field1 = 1;
performOperation(obj1); //takes some time
}
최소한의 RAAI 스레딩 지원에 대한 참조는 Andrei Alexandrescu (see here)의 "Modern C++ design : generic programming and design patterns applied"를 참조하십시오. 다른 리소스도 있습니다 (here)
나는 코드에서 볼 수있는 다른 문제 하나를 설명하려고합니다. 좀 더 정확히 말하자면, obtainMutex와 releaseMutex를 메서드로 가지고 명시 적으로 호출하는 것으로 보이는 문제입니다. 스레드 1이지도를 잠그고 객체를 생성하여 obtainMutex를 호출하고지도를 잠금 해제한다고 가정 해 봅시다. 다른 스레드 (스레드 2라고도 함)가 실행 잠금을 위해 예약 됨 map은 객체의 map1 [id]에 대한 반복자를 가져오고 pObject에 releaseMutex()를 호출합니다 (즉, 코드가 시도하지 않는 버그로 인해 보겠습니다). 먼저 obtainMutex를 호출하십시오.) 이제 스레드 1 일정이 잡히고 어떤 시점에서 호출 releaseMutex(). 그래서 물체는 한 번 잠겼지만 두 번 풀어졌습니다. 내가 말하고자하는 것은 그것이 예외가 발생했을 때 호출이 항상 올바르게 쌍을 이룰 수 있는지, 잠재적으로 잠금을 해제하지 않는 잠재적 인 초기 수익 및 객체 잠금 인터페이스의 잘못된 사용을 확인하는 것이 어려운 작업이라는 것입니다. 또한 스레드 2는지도에서 가져온 pObject를 삭제하고지도에서 지울 수 있습니다. 그러면 스레드 1은 이미 삭제 된 객체가있는 작업으로 이동합니다.
RAII를 사용하면 RAII가 코드를 더 쉽게 이해할 수 있고 (우리 버전을 비교하면 더 짧아집니다) 위의 열거 된 문제 중 일부를 많이 도울 수 있습니다.컨테이너가 될 수 있으므로,
당신이 항목을 추가하고, 따라서 컨테이너를 수정하는
1), 당신은 다른 스레드에서 읽기 액세스를 허용해서는 안 : 대답에 내 의견을 결합
'-> obtainMutex()'가 생성되기 전에 다른 스레드가 obj1에 도착하는 것이 가능하지 않으면 교착 상태가 발생할 수있는 영역이 표시되지 않습니다. 다시 말해'read '나'write'를 위해'map1'에 접근하기 전에'mutexA'를 잠그는 한 괜찮을 것입니다. 그러나'pthread_mutex_unlock (뮤텍스 A)'를지도의 'id'가 그 안에있는 객체의 내용에 따라 바뀌지 않는 한 한 줄 위로 올리면된다고 생각합니다. – milkypostman
'map1'에 대한 업데이트를 위해 다중 스레드를 통해 액세스되는'map'에 저장된 객체가 있습니까? 객체를 thread-safe하게 만드는 것이 더 좋지 않은가? - 그 말을 유감스럽게 생각한다 - obj1-> obtainMutex'를 사용하는 코드? – Jaywalker
몇 년 전 MSVC에서 작업 할 때 표준 라이브러리의 멀티 스레드 버전이있었습니다. thread-safe 버전의 stl을 얻을 수 있다면 적어도 컨테이너 당 뮤텍스 mutexA – davka