2013-03-05 2 views
4

부스트와 같은 최신 C++ 스레딩 라이브러리에 대한 액세스 권한이없는 프로젝트에 다음 코드를 생성했습니다. 내 바램은 범위를 벗어나 자물쇠가 자동으로 해제되도록하는 것입니다.수제 범위 잠금이 잠기지 않습니다.

공유 잠금이 정상적으로 작동합니다. 스레드가 스레드를 획득하면 첫 번째 스레드가 스레드를 해제 할 때까지는 다른 스레드가이를 획득 할 수 없습니다. Scoped는 작동하지 않습니다.

다음은 출력의 의미를 보여줍니다. 나는 각각의 쓰레드에 고유 한 이름을 주었고, 동일한 공유 잠금을 사용하여 Scoped 자물쇠를 인스턴스화하고, '획득'을 인쇄하고, 5 초 동안 자고, '릴리스'를 인쇄 한 다음 범위를 벗어났다. 획득/릴리스 쌍을 얻는 대신에, 나는 4 년 동안 획득 한 것을 5 년 간격으로 빠르게 연속해서 얻는다. Scoped의 잠금 장치를 포인터로 변경하고 획득하기 전에 주소를 인쇄하여 미쳐 있지 않은지 확인했습니다. 동일한 Shared 객체 인 것처럼 보이지만 잠금은 다중 액세스를 방지하지 못합니다.

Lock '140734928395200'. 
acquired: !!!!! 
Lock '140734928395200'. 
acquired: ------- 
Lock '140734928395200'. 
acquired: *************** 
Lock '140734928395200'. 
acquired: ## 
released: !!!!! 
released: ------- 
released: *************** 
released: ## 

여기 Lock.h의 소스 코드입니다 :

#include <pthread.h> 
namespace Lock 
{ 
    class Shared 
    { 
    public: 
    Shared() 
    { 
     ::pthread_mutex_init(&(this->mutex), nullptr); 
    } 
    ~Shared() 
    { 
    } 
    void acquire() 
    { 
     ::pthread_mutex_lock(&(this->mutex)); 
    } 
    void release() 
    { 
     ::pthread_mutex_unlock(&(this->mutex)); 
    } 
    private: 
    pthread_mutex_t mutex; 
    }; 
    class Scoped 
    { 
    public: 
    Scoped(Lock::Shared& lock) : lock(lock) 
    { 
     this->lock.acquire(); 
    } 
    virtual ~Scoped() 
    { 
     this->lock.release(); 
    } 
    private: 
    Lock::Shared& lock; 
    }; 
}; 

여기 테스트를 위해 내 main.cc 파일입니다. 나는 다음과 함께 건물을 짓고있다 :

g++ -std=c++11 -o try -pthread main.cc && ./try 

g ++ 4.7 최신 우분투 시스템.

#include <pthread.h> 
#include <iostream> 
#include "Lock.h" 
#include <unistd.h> 
struct data 
{ 
    data(std::string name, Lock::Shared& lock) : name(name), lock(lock) { ; } 
    std::string name; 
    Lock::Shared& lock; 
}; 
void* doStuff(void* v) 
{ 
    data* d = (data*)v; 
    for (int i = 0; i < 5; i++) 
    { 
    Lock::Scoped(d->lock); 
    //d->lock->acquire(); 
    std::cout << "acquired: " << d->name << std::endl; 
    ::sleep(5); 
    std::cout << "released: " << d->name << std::endl; 
    //d->lock->release(); 
    ::sleep(1); 
    } 
} 
int main(int argc, char* argv[]) 
{ 
    pthread_t fred; 
    pthread_t barney; 
    pthread_t wilma; 
    pthread_t betty; 
    Lock::Shared lock; 
    data f("##", lock); 
    data b("***************", lock); 
    data w("-------", lock); 
    data e("!!!!!", lock); 
    ::pthread_create(&fred, nullptr, doStuff, (void*)&f); 
    ::pthread_create(&barney, nullptr, doStuff, (void*)&b); 
    ::pthread_create(&wilma, nullptr, doStuff, (void*)&w); 
    ::pthread_create(&betty, nullptr, doStuff, (void*)&e); 
    ::pthread_join(fred, nullptr); 
    ::pthread_join(barney, nullptr); 
    ::pthread_join(wilma, nullptr); 
    ::pthread_join(betty, nullptr); 
    return 0; 
} 
+3

합니다. 두 가지 제안 : (1) 우리가 실험 할 수있는 완전한 실행 가능한 예제를 게시하십시오. (2) pthreads 함수의 값을 무시하지 않고 검사합니다. – NPE

+1

출력 버퍼링이 가능합니까? – hmjd

+0

@hmjd : 없어야합니다. std :: endl 버퍼를 플러시합니다. – kwiqsilver

답변

11

문제이다

구성 즉시 소멸된다 temporaray Lock::Scoped를 생성
for (int i = 0; i < 5; i++) 
{ 
    Lock::Scoped(d->lock); 

는, 따라서 의도 된 동기 영향을 미치지 않는다.

for (int i = 0; i < 5; i++) 
{ 
    Lock::Scoped lk(d->lock); 
+0

(+1) 그것을 이겼다. :) – NPE

+0

D' oh! 수업 시간에 문제가 너무 집중되어있어 잘못 사용했는지 확인하지 못했습니다. 감사! – kwiqsilver

5

문제는 여기에 있습니다 : :에 변경

Lock::Scoped(d->lock); 

이 바로 범위를 벗어나 그 익명의 일시적 만듭니다.

는 수정에 이름 부여하려면 : 나는 분명히 잘못 아무것도 볼

Lock::Scoped lck(d->lock); 
관련 문제