2012-02-14 2 views
3

C++에서 개체에 뮤텍스를 사용하는 방법을 이해하려고합니다.개체와 뮤텍스

struct Rope{ 
    int n, steps, offset; 
    //std::mutex mut; 

    Rope() {} 
    Rope(int n, int steps, int offset) : n(n), steps(steps), offset(offset) {} 

    void compute(){ 
    double a[n]; 
    for (int i=0; i<n; i++) 
     a[i] = i + offset; 
    for (int step=0; step<steps; step++) 
     for (int i=0; i<n; i++) 
    a[i] = sin(a[i]); 
    } 

}; 

void runTest(){ 
    int numRuns = 30; 
    int n = 10000; 
    int steps = 10000; 

    std::vector<Rope> ropes; 
    std::vector<std::thread> threads; 
    for (int i=0; i<numRuns; i++) 
    ropes.push_back(Rope(n, steps, i)); 
    for (auto& r : ropes) 
    threads.push_back(std::thread(&Rope::compute, r)); 
    for (std::thread& t : threads) 
    t.join(); 
}  

코드는 그대로 잘 실행, 내 4 코어 머신에서 ~ 4 배의 속도 향상을보고 : 나는 속도 테스트로 사용하고 다음 (사소한) 멀티 스레드 코드가 있습니다. 나는 물론 로프에 아무것도 저장하지 않으므로 뮤텍스가 필요하지 않습니다. 지금 내가 보호해야 할 데이터가 있다고 가정한다면, Rope에 뮤텍스를 첨부하고 (예) compute() 루프 내에서 std :: lock_guard를 호출하고 싶습니다. 하지만 mutex의 주석을 제거하면 할당 및 복사 연산자에 "삭제 된 함수 사용"에 대한 컴파일러 오류가 발생합니다. 내가 목표물을 안전하게 잠그기 위해 무엇을 놓치고 있습니까?

답변

6

클래스 스레드를 만들 수있는 간단한 방법이 문제는이 클래스가 아닌 복사 가능한 수 있다는 것입니다 접근 방법

class cMyClass { 
    boost::mutex myMutex; 
    cSomeClass A; 
public: 
    cSomeClass getA() { 
    boost::mutex::scoped_lock lock(myMutex); 
    return A; 
    } 
}; 

에 뮤텍스 뮤텍스 속성을 추가하고 잠그는 것입니다. 이는 특히 컨테이너의 클래스 객체를 컨테이너에 저장하려는 경우 중요합니다.

뮤텍스를 정적으로 만들어서 만들 수 있습니다.

class cMyClass { 
    static boost::mutex myMutex; 
    cSomeClass A; 
public: 
    cSomeClass getA() { 
    boost::mutex::scoped_lock lock(myMutex); 
    return A; 
    } 
}; 

그러나,이 모두 동일한 뮤텍스를 공유하기 때문에 클래스 블록의 모든 인스턴스가 다른 인스턴스가, 액세스 될 때 것을 의미한다.

이론적으로, 정적이 아닌 뮤텍스를 포함하는 클래스는 복사 생성자와 할당 연산자를 직접 코딩하여 뮤텍스를 제거함으로써 복사 가능하게 만들 수 있습니다. 그러나 이것은 개발이 자주 바뀌는 많은 수의 속성을 가진 클래스의 경우 특히 어렵고 지루한 작업입니다.

클래스가 차단되었을 때 클래스의 모든 인스턴스에 대한 액세스를 차단하는 정적 뮤텍스가 허용되지 않는 경우 가장 좋고 간단한 접근법은 클래스 외부에 뮤텍스를 유지하는 것입니다. 이런 방식으로 클래스의 내부 동작을 노출하는 것은 불행한 일이지만 대안은 훨씬 복잡하고 신뢰할 수 없기 때문에 클래스에 액세스하는 코드 수준에서 뮤텍스를 처리 할 때 자주 상당한 최적화를 찾습니다.

+0

@MikeSeymour 그가 말하는 것에 대해 오해하지 않았다면, 그는 모든 스레드에서 ** 같은 ** 뮤텍스를 사용해야합니다. 이동 의미를 사용하여 컨테이너에 넣는 것은 효과가 없습니다. (반면에 현재 쓰여지는 것처럼 각 스레드는 자체적 인'Rope' 객체를 가지므로 뮤텍스는 필요하지 않습니다. 문제가 명확하게 설명되지 않았을 때 정확한 해결책이 무엇인지 말하기는 어렵습니다.) –

+0

@ Mike Seymour :'std :: mutex'는 움직일 수 없습니다. 'Rope'은 기본적으로'Rope' 생성자마다'std :: mutex'를 구성하여 이동 가능하거나 복사 가능하게 만들 수 있습니다. 또는 James가 암시하는 것처럼 뮤텍스를 정적으로 만드는 것입니다. 이 두 가지 접근법 중 적절한 것은 OP만이 시점에서 알고있는 것입니다. –

+0

내 실수. 게시하기 전에 내 가정을 확인 했어야합니다. –

0

mutex을 (를) 복사 할 수 없습니다. 뮤텍스 복사본을 만드는 것이 무엇입니까? 뮤텍스를 획득하고 해제 할 곳은 이며, 모든 스레드가 동일한 뮤텍스 에 액세스해야하므로 runTest에 정의하고 참조 또는 포인터로 전달해야합니다.