2012-08-02 3 views
1

RW 잠금이 전역 적으로 선언되고 progrmm이 예상대로 실행되는 동안 C++에서이 간단한 스레드 생성 progrm을 가졌지 만 동일한 잠금 선언이 로컬 (즉, 함수 내부)으로 만들어지면 하나의 스레드 다른 스레드가 중단됩니다.스레드가 pthread_rwlock_t에 있습니다.

WORKING :

#include <iostream> 
#include <pthread.h> 

using namespace std; 
int i = 0; 
**pthread_rwlock_t mylock;** //GLOBAL 

void* IncrementCounter(void *dummy) 
{ 
    cout << "Thread ID " << pthread_self() << endl; 
    int cnt = 1; 
    while (cnt < 50) 
    { 
     pthread_rwlock_wrlock(&mylock); 
     ++i; 
     pthread_rwlock_unlock(&mylock); 
     ++cnt; 
    cout << "Thread ID (" << pthread_self() << ") Incremented Value : " << i << endl; 
    } 

} 
int main() 
{ 
     pthread_t thread1,thread2; 
     int ret, ret1; 
     ret = pthread_create(&thread1,NULL,IncrementCounter,NULL); 
     ret1 = pthread_create(&thread2,NULL,IncrementCounter,NULL); 
     pthread_join(thread1,NULL); 
     pthread_join(thread2,NULL); 

} 

* NON WORKING : 이것에 대한 *

#include <iostream> 
#include <pthread.h> 

using namespace std; 
int i = 0; 

void* IncrementCounter(void *dummy) 
{ 
    cout << "Thread ID " << pthread_self() << endl; 
    int cnt = 1; 
    **pthread_rwlock_t mylock;** //LOCAL 
    while (cnt < 50) 
    { 
     pthread_rwlock_wrlock(&mylock); 
     ++i; 
     pthread_rwlock_unlock(&mylock); 
     ++cnt; 
    cout << "Thread ID (" << pthread_self() << ") Incremented Value : " << i << endl; 
    } 

} 
int main() 
{ 
     pthread_t thread1,thread2; 
     int ret, ret1; 
     ret = pthread_create(&thread1,NULL,IncrementCounter,NULL); 
     ret1 = pthread_create(&thread2,NULL,IncrementCounter,NULL); 
     pthread_join(thread1,NULL); 
     pthread_join(thread2,NULL); 

} 

무엇을 할 수있는 가능한 이유?

답변

4

어느 경우에도 mylock 변수를 올바르게 초기화하지 않았습니다. 첫 번째 경우에는 "행운"을 얻고 있습니다. static 선언하는 로컬 경우

pthread_rwlock_t mylock = PTHREAD_RWLOCK_INITIALIZER; 

, 당신이 당신의 스레드가 같은 잠금 장치를 액세스 할 수 있도록하려면 다음이있다 : 글로벌 경우 올바른 초기화 될 것

static pthread_rwlock_t mylock = PTHREAD_RWLOCK_INITIALIZER; 

이 경우 원하는 내용입니다. i에 대한 액세스를 보호하고 있기 때문입니다. 잠금 장치가 데이터와 연결되어야하므로 i이 전역 인 경우 실제로는 mylock이 전역적일 수도 있습니다. 당신이 정말로 (이 경우, 당신이하지 않는) 비 정적 잠금을 원하는 경우


, 다음을 사용 :

pthread_rwlock_destroy(&mylock); 

:

pthread_rwlock_t mylock; 

pthread_rwlock_init(&mylock, NULL); 

은 다음에 함수의 끝에서

+0

설명해 주셔서 감사합니다. 나는 전역 변수에 대해 두 개의 잠금을 가짐에있어 아무런 포인트가 없다는 것을 알고있다. 그러나 두 개의 잠금이있는 경우 두 가지 잠금이 서로 다른 잠금이되므로 잠금이 풀리면 다른 잠금이 해제됩니다. 왜 교착 상태입니까? 하나의 글로벌 변수를 2 개의 다른 잠금으로 잠그지 않아야합니까? 정교하게 주시겠습니까? – user1570478

+0

@ user1570478 : 잠금 장치가 제대로 초기화되지 않았기 때문에 교착 상태입니다. 두 개의 잠금이 있기 때문에가 아닙니다. 초기화되지 않은 잠금을 사용하면 아무 일도 일어나지 않을 수 있습니다. – caf

0

이유는 분명합니다. 사용자가 직접 말할 수도 있습니다 ... 작업 버전에서는 변수가 전역이고, 작동하지 않는 변수는 로컬입니다.

로컬 변수는 해당 호출 중에 함수 내에서만 알 수 있습니다. 따라서 함수가 두 번 호출되면 변수는이 두 호출에서 고유합니다.

로컬 변수를 사용하려면 static으로 표시하면 모든 함수 호출간에 "정적"으로 표시됩니다.

변수 유효 기간 및 유효 기간에 대해 자세히 읽어 보시기 바랍니다.

+0

설명해 주셔서 감사합니다. 나는 전역 변수에 대해 두 개의 잠금을 가짐에있어 아무런 포인트가 없다는 것을 알고있다. 그러나 두 개의 잠금이있는 경우 두 가지 잠금이 서로 다른 잠금이되므로 잠금이 풀리면 다른 잠금이 해제됩니다. 왜 교착 상태입니까? 단일 전역 변수가 2 개의 다른 잠금으로 잠겨 야합니까? 정교하게 주시겠습니까? – user1570478

+0

@ user1570478 잠금이 제대로 초기화되지 않았기 때문에 교착 상태가 될 수 있습니까? caf에서 대답을 참조하십시오. –

1

다른 답변에 덧붙여 C와 C++에서 정적 저장소가있는 모든 변수 (예 : mylock)는 0으로 초기화됩니다. 간체, pthread_rwlock_tstruct입니다.

첫 번째 예에서는 mylock에 정적 저장 기간이 있으므로 모든 내부 구성원이 0으로 초기화되었습니다.우연히, pthread_rwlock_t의 "잠금 해제 됨"상태와 동일합니다. 다른 대답에 언급 된 매크로 PTHREAD_RWLOCK_INITIALIZER은 정확히 모든 것을 0으로 초기화합니다. nptl/sysdeps/pthread/pthread.h에서 찾을 수 있습니다 : 첫 번째 예

#define PTHREAD_RWLOCK_INITIALIZER \ 
{ { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 } } 

따라서 모든 실행은 항상 같은 동작을 전시 할 예정이다 (즉 잠금 해제가 시작됩니다).

두 번째 예에서 mylock은 자동 저장 기간이 있기 때문에 초기화되지 않았습니다. 그런 다음이 동작은 메모리의 초기화되지 않은 영역에 어떤 값이 누적되어 있는지에 따라 달라집니다. 대부분의 경우 잠금은 "잠김"상태에서 시작하지만 운이 좋으면 (불행한 경우) 잠금 해제 상태로 시작됩니다.

+0

이것은 pthread의 한 특정 구현에만 적용된다는 것을주의하십시오. - PTHREAD_RWLOCK_INITIALIZER는 다른 구현에서는 0이 아니어도됩니다 (그렇지 않으면 전혀 존재하지 않아도됩니다!). – caf

+0

참; 'PTHREAD_RWLOCK_INITIALIZER'는 좋은 코딩 방법 이외에 교차 구현 및/또는 버전 간 호환성을 위해 존재한다고 생각합니다. –

+0

예, 예를 들어 pthreads-w32는'((pthread_rwlock_t) -1)'을 사용합니다. – caf

관련 문제