[완료]MUTEX에 관해서 질문드립니다.

poibe의 이미지

스티븐스의 책에서 뮤택스에 관해서 보고있는데요

궁금한것이.

만약 int ndone; 이란것을 전역으로 선언을 하고 두개의 스래드에서 이 변수를 건드린다고 할때

int gNdone;
pthread_mutex_t gNdone_mutext = INITIAL..;

이렇게 선언하고

스레드 안에서는

mutex_lock(&gNdone_mutex);
gNdone++
mutex_unlock(&gNdone_mutex);

이렇게 되어있더군요..

-----------------------
gNdone을 보호할려고 했다면 gNdone을 뮤텍스로 선언해서 이녀석을 락하고 언락해야 하는것아닌가 하는 생각이 들어서입니다.

어떤분은 뮤텍스 락을 하면, 해당부분 전체가 락이된다.머 그러식으로 설명을 하던데..
그러면 만약 스레드가 서로 공유하는 변수나 리스트가 한게가 아니라 여러개라도,
뮤텍스 변수는 하나만 해서 계속 lock, unlock을 하면 되는 것인지요??

어떤 오픈소스 코드에서는

mutex를 H[i];와 같이 선언해서
lock, unlock할때도 &H[i] 씩으로 하던데요.. 이런건 어떻게 되는것인지.... 개념적으로 스티붕 선생님의 책으로만으로는
도무지 잘 않와서 질문드립니다.

그리고, 만약에 HASH TABLE을 위해서
H[12]까지 있고, 각 H[i]는 물려있는 버캣의 해드 주소를 가지고 있어서
스래들은 모두 해쉬테이블을 공유한다고 할때
특정 스래드가 접근하는 H[i]아래의 버캣만 lock을 한다면 그런거이 되는건지요..

전반적으로 뮤텍스에 대해서 개념적으로 잘 설명되어 있는 것이 있다면..
링크라도.. 좀 부탁드립니다. -_ㅜ;;

lifthrasiir의 이미지

뮤텍스는 말 그대로 여러 쓰레드가 같은 코드를 실행하려 하는 상황을 방지(mutual exclusion)하는 역할을 합니다. 뮤텍스를 써도 뮤텍스를 쓰지 않는 다른 코드가 데이터를 변경하거나, 버퍼 오버런 등의 이유로 데이터가 변경되는 경우는 막을 수 없습니다.

체스맨의 이미지

뮤텍 개념을 잡기 위해, 은행 업무를 예로 들면,

업무 보러 간 사람들 = 스레드
은행 직원 = gNdone
번호표 기계 = 뮤텍

로 보시면 됩니다.
과거에 번호표가 없을 때, 은행은 혼란의 극치였습니다. 이런 경우 gNdone 에 해당하는 은행원의 업무는 예측 불허 상태죠. 이게 컴퓨터 세계에서는 동기화되지 않은 스레드들의 실행 결과가 됩니다.

번호표 기계라는 뮤텍이 도입되면, 각 업무 보러 간 사람들은 (스레드) 번호표를 뽑고, 은행 직원을 만나기 위해 대기합니다. 이 대기 상태가 mutex을 잠근 상태에 해당되고, 대기 중이던 하나의 스레드는 은행 직원과 업무를 볼 수 있게 됩니다. 이게

gNdone ++ 입니다.

은행 직원과 업무가 끝나면, 다시 다음 사람을 받습니다. 이것이 뮤텍을 unlock 하는 작업 입니다.

뮤텍을 배열로 선언한 것은, 은행 직원이 여러명 있고 각 직원별로 번호표 기계가 다른 것으로 보시면 됩니다. 그렇게 어려운 개념은 아니에요.

Orion Project : http://orionids.org

poibe의 이미지

#include "upthread.h"
#define NLOOP 5000

int counter;
pthread_mutex_t counter_mutex = PTHREAD_MUTEX_INITIALIZER;

void *doit(void *);

int
main(int argc, char **argv)
{
pthread_t tidA,tidB;

pthread_create(&tidA,NULL,&doit, NULL);
pthread_create(&tidB,NULL,&doit, NULL);

pthread_join(tidA,NULL);
pthread_join(tidB,NULL);

exit(0);
}

void *
doit(void *vptr)
{
int i,val;

for (i = 0; i =< NLOOP; i++)
{
pthread_mutex_lock(&couter_mutex)

val=counter;
printf("%d:%d\n",pthread_self(),val+1);
counter=val+1;

ptrhead_mutex_unlock(&coutner_mutex);
}
return (NULL);
}

---------------------
위의 코드는 스티븐스의 UNIX NETWORK PROGRAMMING 책의 예제 소스입니다.
위에서 counter를 보호할려고 하는건 설명을 통해 그렇게 이해하고 있습니다.

제가 궁금했던것은 counter를 보호해야 하는데,
왜? counter_mutex를 잠궜다 풀었다 하는거냐 이고요.

1. 채스맨님께서 말씀하신 것이... 다른 누가 이야길 하길... doit에 있는 내용들이 모두 잠긴다라는 의미와 비슷하다고 생각하면 될런지요?
- 그렇게 생각하면 그냥 이해가 됩니다.

2. 근데 여기서 더 궁금한것이.. 그럼..만약에 counter라는 전역변수 말고, 다른 counter2라는 전역변수를 선언해 뒀다가..
doit 스레드 않에서 사용을 하면 그넘도 같이 잠기냐는 것입니다.
- 다르게 생각해보면, 뮤텍스 락을 건곳에서의 모든 전역변수들은 모두 잠기냐는것이 저의 질문의 요지입니다.

=> 추가하여 그렇다면, 스레드에서 여러 변수, 리스트들을 보호해야 한다면, 굳이 뮤텍스의 이름을 달리할 이유도 없지 않냐는 겁니다.

Fly to the SKY~~~~~~

"According to your faith, be it unto you!!"

김일영의 이미지

저도 그냥 쓰레드 프로그램을 대충 할 뿐 수준이 높진 못하지만 아는 범위 내에서 설명해보겠습니다.

예제로 올려주신 코드를 보면요.
pthread_create(&tidA,NULL,&doit, NULL); --> 여기서 쓰레드 하나 만들었고(A라고 해 두죠)
pthread_create(&tidB,NULL,&doit, NULL); --> 여기서 쓰레드 또 만들었죠(B라고 해 두죠)

여기서 쓰레드 A나 B나 하는 일은 doit이라는 함수를 실행하는거죠.
어떤게 먼저 실행되는지는 알 수 없고요... 또 어떤게 먼저 뮤텍스를 건 부분을 실행할지도 알 수 없죠.
여하튼 doit 함수 내용을 쭉 실행해갑니다.

그러다가 여하튼 어느 한 쪽이 doit 실행 중에 먼저 뮤텍스를 건 부분을 만날겁니다.
pthread_mutex_lock(&couter_mutex);
제일 먼저 이 코드까지 온 쓰레드가 A라고 하면, A는 이 코드를 실행합니다. 'lock을 거는' 것이죠.

그러고나서 그 직후에 다른 쓰레드도 이 위치까지 딱 왔다고 하더라도
그 쓰레드는 pthread_mutex_lock(&couter_mutex); 를 실행하지 못하고 멈춥니다.
이렇게 멈춘 상태를 'block' 되었다고 하고 'lock이 풀리기를' 기다리고 있다고도 합니다.

그래서 A가 다시 unlock을 해주기 전까지는
lock을 거는 코드 및 그 다음 부분들을 실행하지 못하고 멈춥니다.
이게 'lock'의 역할입니다.

쓰레드 A가 뮤텍스로 보호하는 영역 즉 '임계영역'을 다 실행하고 나면 (아래 부분)
val=counter;
printf("%d:%d\n",pthread_self(),val+1);
counter=val+1;

그 다음에는 ptrhead_mutex_unlock(&coutner_mutex);를 실행하게 되겠죠.
즉 '쓰레드 A가 걸었던' lock이 풀립니다.

쓰레드 A는 볼 일을 다 본 상황이고 이제 lock이 풀렸으니까
이번에는 아까 block되었던 다른 쓰레드 B가 pthread_mutex_lock(&couter_mutex); 를
실행할 수가 있게 됩니다.

그러면 이번에는 쓰레드 B만이 임계영역의 내용을 실행할 수 있는거고요.

그러니까 소스 코드상에서 뮤텍스를 lock하는 부분부터 unlock하는 부분까지는
한 번에 한 쓰레드만 실행할 수 있게 됩니다.
이렇게 해서 counter 라는 변수는 한번에 한 쓰레드만 값을 바꿀 수 있게 하는거고
그걸 '보호'한다고 합니다.
굳이 따지자면 counter라는 변수가 아니라 '임계 영역'을 보호한다고 하는게 정확할 것 같습니다.

뭐 대충 이렇습니다... 도움이 되셨으면 좋겠군요

poibe의 이미지

이야기를 바탕으로 검증할만한 테스트 코드를 한번 만들어봐야 겠네욥~!
^^

Fly to the SKY~~~~~~

"According to your faith, be it unto you!!"

체스맨의 이미지

김일영님께서도 설명해주셨지만, 제 아이디가 들어있으니, 제가 드린 예에 비추어 말씀드리면...

뮤텍은 제가 말씀드린 번호표 기계와 같습니다. 은행 업무보러온 사람들이 스레드라고 말씀드렸죠? 번호표는 사람들을 대기하게 만듭니다. 뮤텍을 잠근다는 것은, 변수들에 접근하는 것을 막는게 아니라, 한 시점에서 하나의 스레드만 통과시키고, 나머지 스레드들은 unlock 되기 전까지 더 이상 실행되지 않도록 막는 것입니다.

은행의 번호표 처리처럼요. 잘 생각해보시면 같은 개념이 될 겁니다.
아마 이로써 1, 2번에대한 답변이 될 겁니다.

그래서, 여러 변수들을 보호하는 경우, 그 변수를 보는 게 아니라, '그 변수들에 접근하는 스레드'를 봐야합니다. 그래서 스레드가 동시에 접근함으로써 실행이 불합리해질 수 있는 부분에, 뮤텍이나 여타 동기화 개체들을 설치하는 겁니다.

은행 직원이 업무보는데 여러사람이 동시에 업무 요구를 하면 불합리해지기 때문에, 번호표 기계를 설치했듯이요.

Orion Project : http://orionids.org

익명 사용자의 이미지

"의자" 라는 리소스는 1명밖에 사용할 수 없습니다.

동시에 여러명 앉으면 부서지기 때문에, 1명만 앉도록 해야되는데,
그러기 위해서 "권한 막대기"을 만들었습니다.

이 막대기을 들고 있는 사람만이 의자에 앉을 수 있는거죠.

바꿔말하면 의자가 counter가 되겠고, 막대기가 counter_mutex가 되겠네요.

체스맨의 이미지

덧붙여, 스티븐스씨의 저 예제는, 예제를 위한 예제일 뿐입니다. ( 비하하는 건 아니구요. )

실제 상황에서는 저 부분이 동기화될 필요가 있는가에 대한 평가가 필요합니다. 동기화는 스레드 데드락을 유발할 수 있고(물론 이건 잘못 작성한 코드립니다), 다중 스레드 실행에서 병목이 되기도 하니까요. ( 왜냐면, 스레드마다 자유롭게 실행되는 것을 저지하는 게 뮤텍의 역할이니까요. )

Orion Project : http://orionids.org

poibe의 이미지

갈수록,, 설계의 중요성을 깨닫고 있는 요즘입니다. ^^

근데 이거 완료됐다고 하기는법을 모르겠습니다. -_-;

Fly to the SKY~~~~~~

"According to your faith, be it unto you!!"

댓글 달기

Filtered HTML

  • 텍스트에 BBCode 태그를 사용할 수 있습니다. URL은 자동으로 링크 됩니다.
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param><hr>
  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.

BBCode

  • 텍스트에 BBCode 태그를 사용할 수 있습니다. URL은 자동으로 링크 됩니다.
  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param>
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.

Textile

  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • You can use Textile markup to format text.
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param><hr>

Markdown

  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • Quick Tips:
    • Two or more spaces at a line's end = Line break
    • Double returns = Paragraph
    • *Single asterisks* or _single underscores_ = Emphasis
    • **Double** or __double__ = Strong
    • This is [a link](http://the.link.example.com "The optional title text")
    For complete details on the Markdown syntax, see the Markdown documentation and Markdown Extra documentation for tables, footnotes, and more.
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param><hr>

Plain text

  • HTML 태그를 사용할 수 없습니다.
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.
  • 줄과 단락은 자동으로 분리됩니다.
댓글 첨부 파일
이 댓글에 이미지나 파일을 업로드 합니다.
파일 크기는 8 MB보다 작아야 합니다.
허용할 파일 형식: txt pdf doc xls gif jpg jpeg mp3 png rar zip.
CAPTCHA
이것은 자동으로 스팸을 올리는 것을 막기 위해서 제공됩니다.