[완료] pthread_mutex_lock ( )의 위치에 따라 다르게 출력되는 문제..
안녕하세요. *^^*
요즘 날씨도 꾸물꾸물한데 다들 별일 없으신가요?
제가 열혈강의 소켓 책으로 소켓프로그래밍을 한창 공부하고 있는데
멀티스레드에서의 동시접근 문제를 해결하기 위한 mutex 부분에서 이해가 되지 않는 부분이 있어 질문드립니다.
pthread_create(&t1, NULL, thread_increment, &thread1); pthread_create(&t2, NULL, thread_increment, &thread2); void* thread_increment(void *arg) { int i; for(i=0; i<5; i++){ pthread_mutex_lock(&mutx); sleep(1); number++; printf("excution : %s, number : %d\n",(char*)arg, number); pthread_mutex_unlock(&mutx); } }
위 코드를 실행하면 다음과 같은 결과가 나옵니다
excution : A Thread, number : 1
excution : B Thread, number : 2
excution : A Thread, number : 3
excution : B Thread, number : 4
excution : A Thread, number : 5
excution : B Thread, number : 6
excution : A Thread, number : 7
excution : B Thread, number : 8
excution : A Thread, number : 9
excution : B Thread, number : 10
그 다음 sleep()에 주석을 하고 실행하거나 pthread_mutex_unlock(&mutx)의 위치를
printf() 위로 올리면 대부분의 경우 다음과 같이 출력됩니다.
excution : A Thread, number : 1
excution : A Thread, number : 2
excution : A Thread, number : 3
excution : A Thread, number : 4
excution : A Thread, number : 5
excution : B Thread, number : 6
excution : B Thread, number : 7
excution : B Thread, number : 8
excution : B Thread, number : 9
excution : B Thread, number : 10
먼저 pthread_mutex_lock()을 실행시킨 A가 락을 걸고 그 다음인 B가 대기하고 있다 A가 unlock를 실행하면
B가 대기상태를 풀고 임계영역을 실행해야 하는거라고 이해하고 있었는데 이해를 잘 못하고 있는거 같습니다.
pthread_mutex_lock,unlock의 위치가 스레드의 접근순서에 영향을 주는거 같은데 그 원리를 잘 모르겠습니다.
힌트를 좀 얻을 수 있을까요? 부탁드리겠습니다 ^_^/
pthread_mutex_unlock으로
pthread_mutex_unlock으로 릴리즈된 락을 어느 스레드가 잡을지는 OS의 스케쥴링 정책에만 영향을 받습니다.
즉 먼저 기다렸다고 먼저 잡는다는 보장이 없습니다.
감사합니다!
좋은 답변 감사드립니다 ^^
그렇지만 릴리즈되는 시점에서 기다리고 있는 스레드는 하나뿐이지 않나요??
대기중이였던 스레드는 unlock을 실행한 스레드가 다시 루프를 돌아 다시 lock을 실행할때까지도
잡지 못할 수도 있다는 말씀이신가요??
------------
힘들면 즐겁다.
------------
힘들면 즐겁다.
첫번째 스레드가
첫번째 스레드가 루프가 끝나서 다시 pthread_mutex_lock 을 부르는 동안에 두번째 스레드가 실행된다는 보장이 없으면 마찬가지입니다;
아 그렇군요!!
아 보장이 안되는군요..그렇다면 pthread_mutex_unlock(&mutx)의 위치를 printf() 위로 올렸을 경우에도 저런 출력이 나오던데 이거 역시 같은 이유때문인가요??
------------
힘들면 즐겁다.
------------
힘들면 즐겁다.
반드시 thread 전환을 시키고 싶다면...
pthread_mutex_unlock에서 pthread_mutex_lock 사이의 구간에 sleep을 넣으면 됩니다.
지금은 mutex가 잠긴 상태에서 sleep을 하고 있어서 thread 전환이 되더라도 다시 thread 1이 실행 순서를 먼저 잡을 수 밖에 없습니다. (운 좋으면 thread 2로 전환될 수도 있습니다) unlock에서 lock 사이의 구간이 너무 짧은 시간에 끝나므로 loop의 실행 횟수를 늘리거나 그 사이에 sleep을 넣어서 원하는 동작을 수행할 수 있습니다.
질문하나만 더 할께요 'ㅡ'
mutex가 잠긴 상태에서 sleep을 하고 있어 thread 전환이 되더라도
다시 thread1이 실행순서를 잡을 수 밖에 없다고 하셨는데..
혹시 이유가 thread2가 오래 대기하고 있다보니 스케쥴링 우선순위가 thread1보다
밀려서 그런건가요??
------------
힘들면 즐겁다.
------------
힘들면 즐겁다.
mutex를 잠그고 있잖아요.
mutex가 풀릴 때까지 못하죠.
pthread를 좀더 배우게 되면 조건변수를 배우게 될테고 그러면
원하시는 바를 정확히 하실 수 있을 겁니다.
sleep을 한다고 해서
sleep을 한다고 해서 "반드시" thread 전환이 된다는 보장은 없습니다. 테스트하고 있는 특정 시스템에서 높은 확률로 될 뿐이죠. 그 시스템의 library가 업그레이드되거나, load가 많이 걸리거나, 시스템을 바꾸거나 하면 언제든 깨질 수 있습니다.
thread를 쓰는 코드에서 "sleep을 넣어야 동작하는 코드"는 그냥 잘못된 코드라고 생각하는 게 속편합니다.
예. "반드시" 보장되지는 않습니다.
급하게 글을 쓰느라 어감을 정확히 전달하지 못했군요.
다시 읽어보니 그렇게 해석이 되는 걸 알았습니다.
"반드시"는 "굳이"로 바꾸겠습니다.
지적 감사합니다.
감사합니다!
많은 분들의 좋은 말씀 감사드립니다'ㅡ'/
------------
힘들면 즐겁다.
------------
힘들면 즐겁다.
댓글 달기