pthread 에서 lock 과 unlock 에 대해서 질문입니다.

sugarlessgirl의 이미지

안녕하세요..
unix network programming vol.2 를 보다가 잘 이해가 안가는 것이 있어서 질문 드립니다.

void * produce(void *arg)
{
                ...
  Pthread_mutex_lock(&nready.mutex);
  if (nready.nready == 0)
    Pthread_cond_signal(&nready.cond);
  nready.nready++;
  Pthread_mutex_unlock(&nready.mutex);
                ... 
}

void *
consume(void *arg)
{
    int     i;

    for (i = 0; i < nitems; i++) {
        Pthread_mutex_lock(&nready.mutex);
        while (nready.nready == 0)
            Pthread_cond_wait(&nready.cond, &nready.mutex);
        nready.nready--;
        Pthread_mutex_unlock(&nready.mutex);

        if (buff[i] != i)
            printf("buff[%d] = %d\n", i, buff[i]);
    }
    return(NULL);
}

소스는 이런데요..

pthread_cond_wait 가 실행되면, 자신이 lock 하고 있는 mutex 를 unlock 시키고 블락되고, 리턴될때 unlock 한 Mutex 를 다시 Lock 한다고 알고 있습니다.

그럼 produce 함수에서, Pthread_cond_signal 로 wait 되어있는 thread 를
깨울때,

produce 함수에서 Pthread_mutex_unlock 까지 처리한 뒤에,
wait 되어있는 쓰레드를 깨웁니까?

아니면,
Pthread_cond_signal 이 실행되는 순간, 자신을 block 시키고,
wait 하고 있는 thread 를 깨우고, 그 쓰레드가 mutex 를 unlock 하면,
다시 깨어나 작업을 진행하게 되는건가요?

아니면, 언제 자신을 block 하고, wait 되어 있는 thread 를 깨우는지
그 시점을 전혀 예측 할 수 없는 건가요?

뒷 페이지(170) 에 보면 Avoiding Lock Conflicts 부분에서,

Quote:
In a worst-case scenario, we could imagine the system immediately scheduling the thread that is signaled; that thread runs and then immediately stops, because it cannot acquire the mutex.

이런 말이 나오는데요..
제가 위에서 질문한 예측 불가능한 상황을 말하는 것인가요?

이 부분 확실히 이해하고 넘어가야 될 것 같은데..
뭐가 어떻게 돌아가는 건지 모르겠습니다.

아시는 분 도움 부탁드려요..
감사합니다.

케인의 이미지

대기하는 쓰레드를 A, 시그널을 발생하는 쓰레드를 B라고 보죠.
다음과 같은 순서로 실행됩니다.
mutex_lock(A) -> cond_wait call(A) -> mutex_lock(B) -> cond_signal(B) -> mutex_unlock(B) -> cond_wait return(A) -> mutex_unlock(A)

man 페이지에 있는 내용은 cond_signal(B) 이후에 mutex_unlock(B)하기
전까지 cond_wait return(A)를 못한다는 의미입니다.
다시말해, 시그널을 받아서 깨어났지만, B가 mutex_lock을 가지고있기 때문에
다시 대기 상태로 들어간다는 의미이지요. (물론 깨어났다가 대기한다고
표현되어 있지만, 그리 비효율적인 동작은 아닙니다.)

sunyzero의 이미지

일반적으로 이렇게 하는 이유는 synchronization문제때문입니다. wait 상태에 들어간 녀석이 signal을 받고 작동할때는 대부분 produce와 같은 일감을 주는 녀석이 일감을 주고 작동하게 되는데, 이때 시스템의 미묘한 시간차이로 인해서 이 함수내에서의 모든 오퍼레이션이 작동하고 리턴하기전에 consume에 있는 wait 된 녀석이 더 빨리 깨어나면 안되기 때문에 mutex를 이용하는 것이죠.

따라서 위와 같이 mutex를 걸지 않고 사용할경우에는 timing error에 빠질 수 있는 경우도 있습니다. 위의 ready 를 ++ 시키는 도중에 아랫쪽 -- 가 실행되는 재수없는 경우를 볼수도 있기 때문입니다. 이런 문제는 시그널처리에서도 똑같이 발생가능합니다. 흠... 시그널쪽이 조금더 복잡하죠. atomic하다라고 해줄 수 있도록 이런 프로그램은 신경써주는게 가장 중요하다고 생각됩니다.

PS) 윗분이 텍스트 그림까지 그리셔서 신경을 많이 써서 답변해주셨네요. 그리고 고양이 이쁘군요. 저도 예전에 페르샨하나 키웠는데... 지금은... -.ㅜ

========================================
* The truth will set you free.

댓글 달기

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
이것은 자동으로 스팸을 올리는 것을 막기 위해서 제공됩니다.