프로그래밍

pthread signaling (pthread_cond_signal) 의문점

PThread에서 signaling 하기 전후로 mutex를 넣어서 시그널을 보호하는 다음 구조를 가지는데

예 [1] https://blog.naver.com/PostView.nhn?blogId=leekasong&logNo=221816768753&categoryNo=8&parentCategoryNo=0&viewDate=&currentPage=1&postListTopCurrentPage=1&from=search

예 [2] https://stackoverflow.com/questions/4544234/calling-pthread-cond-signal-without-locking-mutex

 

 

thread 1 producer:
    pthread_mutex_lock(&mutex);

    g_shared_val = 1;                 // setter
    pthread_cond_signal(&cond);  // signal
    pthread_mutex_unlock(&mutex);

 

thread 2 consumer:
    pthread_mutex_lock(&mutex);
    pthread_cond_wait(&cond, &mutex);  // wait signal

    local_val = g_shared_val;                  // getter
    pthread_mutex_unlock(&mutex);

 

 

Q1

thread2가 먼저 구동시

여기서 thread2가 먼저 mutex locking 후 wait에 걸리고

thread1이 그 다음 mutex에 접근하면 mutex로 진입 불가해서

thread1이 무한 대기 걸려야 하는거 아님?

왜 동작이 됨?

 

Q2

thread1이 먼저 구동시

pthread_cond_wait이 없는데, pthread_cond_signal 신호가 왜 thread2 다음 구동 시에 pthread_cond_wait이 풀림??

mutex locking으로 인해서 thread2는 pthread_cond_wait에 도달하지 못 한 상태인데??

pthread_cond_wait 중인 쓰레드가 있어야지 pthread_cond_signal로 wakeup이 되는거 아님?

그리고 pthread_cond_wait 중인 쓰레드가 없으면 pthread_cond_signal은 무시되는거 아님?

 

* 판단 미스인듯 정상 무시되는 것으로 보임

 

 

 

 

 

 

`````````````````````````````````````````````````

풀 소스

`````````````````````````````````````````````````

 

 

 

/* inc */

#include <stdio.h>

#include <stdint.h>

#include <pthread.h>

#ifdef __linux__

#include <unistd.h>  // POSIX sleep

#define msleep(time) usleep(time * 1000)  // linux nanoseconds timer

#endif  // __linux__

#if (defined(_WIN32) || defined(_WIN64))

#include <windows.h> // Win32 Win32

#define msleep(time) Sleep(time)          // win32 milliseconds timer

#endif // _WIN32, _WIN64

 

/* shared memory */

int32_t          g_flag_run = 1;

int32_t          g_val = 0;

pthread_cond_t   g_cond;

pthread_mutex_t  g_mutex;

 

/* thread entry function */

void* thread_producer(void *p_entry_arg) {

 

    // stack

    int32_t thread_id = *((int32_t*)p_entry_arg);

    int32_t loop = 0;

    int32_t iret;

 

    // loop

    msleep(100);    // sleep

    printf("[Producer #%d] thread is started\n", thread_id);

    while (g_flag_run) {

        iret = pthread_mutex_lock(&g_mutex);

        if (iret != 0) {

            printf("[Producer #%d] locking is failed\n", thread_id);

        }

        ++g_val;

        pthread_cond_signal(&g_cond);

        pthread_mutex_unlock(&g_mutex);

        printf("[Producer #%d] send %d\n", thread_id, g_val);

 

        msleep(200);    // sleep

        ++loop;

    }

    printf("[Producer #%d] thread is reached the end point\n", thread_id);

    return NULL;

}

 

/* thread entry function */

void* thread_consumer(void *p_entry_arg) {

 

    // stack

    int32_t thread_id = *((int32_t*)p_entry_arg);

    int32_t loop = 0;

    int32_t iret;

    int32_t local_val = 0;

 

    // loop

    printf("[Consumer #%d] thread is started\n", thread_id);

    while (g_flag_run) {

 

        iret = pthread_mutex_lock(&g_mutex);

        if (iret != 0) {

            printf("[Consumer #%d] locking is failed\n", thread_id);

            continue;

        }

        if (1) {

            pthread_cond_wait(&g_cond, &g_mutex);

            local_val = g_val;

            printf("[Consumer #%d]          got %d\n", thread_id, local_val);

        }

        pthread_mutex_unlock(&g_mutex);

 

        msleep(1);  // sleep

        ++loop;

    }

    printf("[Consumer #%d] thread is reached the end point\n", thread_id);

    return NULL;

}

 

/* main thread */

void run(void) {

 

    // stack

    uint32_t uret;

    int32_t iret;

 

    /* thread */

    pthread_t thread[2];

    int32_t   arg[2] = {0, 1};

 

    /* creator */

    iret = pthread_cond_init(&g_cond, NULL);

    if (iret != 0) {

        printf("pthread_cond_init is failed (%d)\n", iret);

    }

    iret = pthread_mutex_init(&g_mutex, NULL);

    if (iret != 0) {

        printf("pthread_mutex_init is failed (%d)\n", iret);

    }

    iret = pthread_create(&thread[0], NULL, thread_producer, &(arg[0]));

    if (iret != 0) {

        printf("pthread_create is failed (%d)\n", iret);

    }

    iret = pthread_create(&thread[1], NULL, thread_consumer, &(arg[1]));

    if (iret != 0) {

        printf("pthread_create is failed (%d)\n", iret);

    }

 

    // ctrl func

    printf("[Main thread] msleep is started\n");

    msleep(5 * 1000);

    printf("[Main thread] Sleep is done\n");

 

    // destroyer

    printf("[Main thread] Destroyer is started (with 2sec sleeping)\n");

    g_flag_run = 0;

    msleep(2000);

    for (int32_t i = 0; i < 2; i++) {

        pthread_cancel(thread[i]);

        iret = pthread_detach(thread[i]);

        if (iret != 0) {

            printf("[Main thread] pthread_detach is failed (%d)\n", iret);

        }

    }

    pthread_mutex_destroy(&g_mutex);

    pthread_cond_destroy(&g_cond);

    printf("[Main thread] Destroyer is done\n");

}

 

/* main */

int32_t main(void) {

    run();

    return 0;

} // main()

 

````````````````````````````````````````````````

4개의 댓글

2024.03.02

"These functions atomically release mutex and cause the calling thread to block on the condition variable cond"

"Upon successful return, the mutex is locked and owned by the calling thread."

- https://www.ibm.com/docs/en/aix/7.3?topic=p-pthread-cond-wait-pthread-cond-timedwait-subroutine

 

pthread_cond_wait 때문에 consumer 스레드에서 mutex 해제됨 => producer 진행 => cond 설정 => consumer 돌아감 => 반복

1
2024.03.02
@OpenGL47

정말 감사합니다.

브레이킹 같이 찍어보면; consumer mutex락 => consumer cond wait 도달 => consumer mutex 강제 해제 => producer mutex 락 => producer cond => producer mutex 언락 => consumer 돌아감 (스케쥴링이 알아서) => consumer mutex 락 => consumer cond wait 리턴 => consumer mutex 언락 => 반복

이 순서인 것 같네요

뭔 순서가 ㅋㅋㅋㅋㅋ 감사합니다. 거참 동작이 어렵게 되어 있네요. 다음부터는 IBM AIX 문서 잘 참고하도록 하겠습니다.

1
2024.03.02
@OpenGL47
0
2024.03.02
@아리
0
무분별한 사용은 차단될 수 있습니다.
번호 제목 글쓴이 추천 수 날짜 조회 수
180507 [잡담] 유튜브 프리미엄 우회 질문드립니당 개드립눈팅4년 0 23 분 전 23
180506 [잡담] 블랙샤크v2 pro 2023 vs 소니 mv1 추천좀 게임게임하자 0 25 분 전 10
180505 [컴퓨터] 인텔 그래픽 드라이버 최신화 인식 왜이따위임? 1 넌뭔데시비냐 0 1 시간 전 65
180504 [모바일] 안드로이드 카메라 어플중에 쓸만한거 뭐있음? 1 일째다이어트하는중 0 1 시간 전 26
180503 [컴퓨터] 집에서 투 컴퓨터 사용시 키보드 마우스 세팅 4 해물잠봉 0 2 시간 전 68
180502 [잡담] 동글 사려는데 싼거사도됨? 5 제로콜라는닥터페... 0 5 시간 전 91
180501 [컴퓨터] 가난개붕이 글카샀다 11 69746974 0 5 시간 전 169
180500 [컴퓨터] 로지텍 무선마우스가 g502x 이거 많이씀?? 9 울그락푸르락 1 6 시간 전 114
180499 [컴퓨터] DDR5는 렘오버한거 차이많이남? 15 창원토박이 0 8 시간 전 194
180498 [컴퓨터] 형들 제품키만 파는것들 써도 되는거야? 4 우루루옳지 0 8 시간 전 100
180497 [잡담] 시네빔 써본 개붕이 있어? 4 따뜻한젤라또 0 8 시간 전 49
180496 [컴퓨터] 다나와에서 컴터 하나 사려고하는데 6 바나나사탕 0 8 시간 전 59
180495 [잡담] 게이밍 노트북 중고 가성비 어때보임? 6 ST11223 0 9 시간 전 140
180494 [컴퓨터] 책상 인증 5 69746974 0 10 시간 전 156
180493 [컴퓨터] 프레임 고정하는 이유가 뭔가요? 5 우루루옳지 0 11 시간 전 161
180492 [모바일] 통신사에 공유기 교체해달라하면 해주나? 5 뱅갈고양이육성중 0 11 시간 전 136
180491 [모바일] 중고폰 선택장애 도와주세요 5 호래빙 0 11 시간 전 69
180490 [컴퓨터] 캐붕이 컴퓨터 어떠냐 9 Benetton 0 13 시간 전 158
180489 [컴퓨터] 형들 컴퓨터 파워가 문제일 가능성이 있을까요? 10 부터시작하는이세... 0 13 시간 전 113
180488 [컴퓨터] 윈도우 ㅅㅂ 왜이러냐 바이러스 관련 업데이트 7 정병장기입원 0 20 시간 전 193