Linux 다 중 스 레 드 프로 그래 밍 상세 설명 - 조건 변수 pthreadcond_t

상기 세 편의 박문 을 참고 하여 링크 는 다음 과 같다.
http://blog.csdn.net/ithomer/article/details/6031723
http://blog.sina.com.cn/s/blog_825085b601018xfp.html
http://blog.csdn.net/ffilman/article/details/4871920
다 중 스 레 드 프로 그래 밍 에서 A 스 레 드 는 B 스 레 드 조건 이 완 료 된 후에 계속 진행 해 야 합 니 다. 여기 서 기다 리 는 방식 은 두 가지 가 있 습 니 다.
1. 자물쇠 + 폴 링 사용
이런 방법 을 사용 하면 쉽게 실현 할 수 있 지만 일정한 성능 소모 가 있 을 것 이다. 그 중 하 나 는 바로 한 번 의 문의 가 결과 가 없 으 면 얼마 만 에 다음 번 의 문의 가 진행 되 고 간격 이 너무 짧 으 며 소모 하 는 CPU 자원 이 비교적 많 고 간격 이 너무 길 어서 신속하게 요청 에 응 하지 못 하 는 것 이다.
그래서 이런 방법 은 추천 이 아 닙 니 다.
2. 조건 변수의 스 레 드 동기 화 사용 (추천)
차단 과 정보 방식 을 채택 하면 자원 의 낭 비 를 크게 줄 이 고 실시 간성 을 증가 시 킬 수 있다
스 레 드 조건 변수 pthreadcond_t
스 레 드 대기 조건
int pthread_cond_timedwait(pthread_cond_t *restrict cond,pthread_mutex_t *restrict mutex,const struct timespec *restrict abstime);
int pthread_cond_wait(pthread_cond_t *restrict cond,pthread_mutex_t *restrict mutex); 
알림 함수
모든 스 레 드 알림
int pthread_cond_broadcast(pthread_cond_t *cond); 
스 레 드 하나만 알려 주기
int pthread_cond_signal(pthread_cond_t *cond); 
---------------------------------------------------------------------------------
올 바른 사용법
 pthread_cond_wait 사용법:
pthread_mutex_lock(&mutex);
while(condition_is_false)
  {
 pthread_cond_wait(&cond,&mutex);
 }
condition_is_false=true;  //이 조작 은 자물쇠 가 달 린 것 이다. 즉, 하나의 스 레 드 만 이 동시에 이곳 에 들 어 온 다 는 것 이다.
pthread_mutex_unlock(&mutex);
 ----------------------------------------------------
pthread cond signal 용법: 
pthread_mutex_lock(&mutex);
condition_is_false=false;
pthread_cond_signal(&cond)
pthread_mutex_unlock(&mutex)
--------------------------------------------------------
 위의 용법 을 기억 하 세 요!! pthread cond broadcast 를 잘못 사용 하지 않도록 모든 조건 변 수 를 방출 할 수 있 습 니 다.
다음은 pthread cond XX 의 용법 입 니 다.
1. 조건 변수 pthread cond init 초기 화
#include
int pthread_cond_init(pthread_cond_t *cv,
const pthread_condattr_t *cattr);
반환 값: 함수 가 0 을 성공 적 으로 되 돌려 주 었 습 니 다. 다른 반환 값 은 모두 오 류 를 표시 합 니 다.
조건 변 수 를 초기 화 합 니 다. 매개 변수 cattr 가 빈 포인터 일 때 함 수 는 결 성 된 조건 변 수 를 만 듭 니 다. 그렇지 않 으 면 조건 변수의 속성 은 cattr 의 속성 값 에 의 해 결 정 됩 니 다. pthread cond init 함 수 를 호출 할 때 매개 변수 cattr 는 빈 포인터 로 cattr 의 속성 은 결 성 속성 입 니 다. 전 자 는 cattr 가 사용 하 는 메모리 비용 이 필요 하지 않 습 니 다. 이 함 수 는 cattr 가 사용 하 는 메모리 비용 을 되 돌려 줍 니 다.조건 변 수 는 매개 변수 cv 가 가리 키 는 메모리 에 저 장 됩 니 다.
매크로 PTHREAD COND INITIALIZER 를 사용 하여 정적 으로 정 의 된 조건 변 수 를 초기 화 할 수 있 습 니 다. 속성 이 부족 합 니 다. 이것 은 pthread cond init 함수 로 동적 으로 분 배 된 효과 와 같 습 니 다. 초기 화 할 때 오류 검 사 를 하지 않 습 니 다. 예 를 들 어:
pthread_cond_t cv = PTHREAD_COND_INITIALIZER;
여러 스 레 드 에서 조건 변 수 를 동시에 초기 화 할 수 없습니다. 조건 변 수 를 다시 초기 화하 거나 풀 어야 할 때 프로그램 은 이 조건 변 수 를 사용 하지 않도록 해 야 합 니 다.
2. 조건 변수 에 pthread cond wait 차단
#include
int pthread_cond_wait(pthread_cond_t *cv,
pthread_mutex_t *mutex);
반환 값: 함수 가 0 을 성공 적 으로 되 돌려 주 었 습 니 다. 다른 반환 값 은 모두 오 류 를 표시 합 니 다.
함 수 는 mutex 매개 변수 가 가리 키 는 상호 배척 자 물 쇠 를 풀 고 현재 스 레 드 를 cv 매개 변수 가 가리 키 는 조건 변수 에 막 습 니 다.
막 힌 스 레 드 는 pthread cond signal 함수, pthread cond broadcast 함수 에 의 해 깨 어 날 수도 있 고 신호 가 끊 긴 후에 깨 어 날 수도 있 습 니 다.
pthread cond wait 함수 의 반환 은 조건 의 값 이 반드시 변 한 것 을 의미 하지 않 으 며 조건 의 값 을 다시 검사 해 야 합 니 다.
pthread cond wait 함수 가 돌아 올 때 해당 하 는 상호 배척 자 물 쇠 는 현재 스 레 드 에 의 해 잠 겨 있 습 니 다. 함수 가 잘못 되 었 더 라 도 돌아 갑 니 다.
일반적인 조건 표현 식 은 상호 배척 잠 금 보호 하에 서 검 사 됩 니 다. 조건 표현 식 이 만족 하지 않 을 때 스 레 드 는 이 조건 변수 에 저 장 됩 니 다. 다른 스 레 드 가 조건 값 을 바 꾸 고 조건 변수 에 신 호 를 보 낼 때 이 조건 변수 에 있 는 스 레 드 나 모든 스 레 드 가 깨 어 날 때 까지 기다 리 고 있 습 니 다. 이 어 해당 하 는 상호 배척 을 다시 차지 하려 고 합 니 다.자물쇠
조건 변수 에 막 힌 스 레 드 가 깨 어 날 때 까지 pthread cond wait ()함수 가 이전 조건 의 값 을 되 돌려 줄 수 있 습 니 다. 따라서 함수 가 돌아 온 후, 해당 하 는 상호 배척 자 물 쇠 를 잠 그 기 전에 조건 값 을 다시 테스트 해 야 합 니 다. 가장 좋 은 테스트 방법 은 pthread cond wait 함 수 를 순환 적 으로 호출 하고, 조건 을 만족 시 키 는 표현 식 을 순환 적 인 종료 조건 으로 설정 하 는 것 입 니 다. 예 를 들 어:
pthread_mutex_lock();
while (condition_is_false)
pthread_cond_wait();
pthread_mutex_unlock();
같은 조건 변수 에 있 는 서로 다른 스 레 드 가 방출 되 는 순 서 를 막 는 것 은 일정 하지 않다.
메모: pthread cond wait () 함 수 는 종료 점 입 니 다. 이 함 수 를 호출 할 때 걸 려 있 는 종료 요청 이 있 고 스 레 드 가 종료 할 수 있 습 니 다. 이 스 레 드 는 종료 되 고 사후 처리 함 수 를 실행 하기 시작 합 니 다. 이 때 조건 변수 와 관련 된 상호 배척 잠 금 은 잠 겨 있 습 니 다.
3. 조건 변수 에 있 는 차단 pthread cond signal 해제
#include
int pthread_cond_signal(pthread_cond_t *cv);
반환 값: 함수 가 0 을 성공 적 으로 되 돌려 주 었 습 니 다. 다른 반환 값 은 모두 오 류 를 표시 합 니 다.
함 수 는 지정 한 조건 변수 에 막 힌 스 레 드 를 방출 하 는 데 사 용 됩 니 다.
상호 배척 자물쇠 의 보호 하에 해당 하 는 조건 변 수 를 사용 해 야 합 니 다. 그렇지 않 으 면 조건 변수 에 대한 잠 금 해 제 는 잠 금 조건 변 수 를 잠 그 기 전에 발생 하여 잠 금 을 해제 할 수 있 습 니 다.
조건 변수 에 막 힌 모든 스 레 드 를 깨 우 는 순 서 는 스 케 쥴 러 정책 에 의 해 결 정 됩 니 다. 스 레 드 의 스 케 쥴 러 정책 이 SCHED OTHER 형식 이 라면 시스템 은 스 레 드 의 우선 순위 에 따라 스 레 드 를 깨 웁 니 다.
조건 변수 에 스 레 드 가 막 히 지 않 으 면 pthread cond signal () 을 호출 하 는 것 은 효과 가 없습니다.
4. 지 정 된 시간 까지 pthread cond timedwait 차단
#include
#include
int pthread_cond_timedwait(pthread_cond_t *cv,
pthread_mutex_t *mp, const structtimespec * abstime);
반환 값: 함수 가 0 을 성공 적 으로 되 돌려 주 었 습 니 다. 다른 반환 값 은 모두 오 류 를 표시 합 니 다.
함수 가 일정한 시간 이 되면 조건 이 발생 하지 않 아 도 차단 을 해제 합 니 다. 이 시간 은 매개 변수 abstime 에서 지정 합 니 다. 함수 가 돌아 올 때 해당 하 는 상호 배척 자 물 쇠 는 함수 가 잘못 되 더 라 도 잠 겨 있 습 니 다.
메모: pthread cond timedwait 함수 도 종료 점 입 니 다.
시간 초과 매개 변 수 는 하루 중 어느 시간 을 말 합 니 다. 예 를 들 어:
pthread_timestruc_t to;
to.tv_sec = time(NULL) + TIMEOUT;
to.tv_nsec = 0;
시간 초과 되 돌아 오 는 오류 코드 는 ETIMEDOUT 입 니 다.
5. 막 힌 모든 스 레 드 pthread cond broadcast 방출
#include
int pthread_cond_broadcast(pthread_cond_t *cv);
반환 값: 함수 가 0 을 성공 적 으로 되 돌려 주 었 습 니 다. 다른 반환 값 은 모두 오 류 를 표시 합 니 다.
함수 가 pthread cond wait 함수 에 의 해 특정한 조건 변수 에 막 힌 모든 스 레 드 를 깨 웁 니 다. 매개 변수 cv 는 이 조건 변 수 를 지정 하 는 데 사 용 됩 니 다. 스 레 드 가 이 조건 변수 에 막 히 지 않 았 을 때 pthread cond broadcast 함수 가 잘못 되 었 습 니 다.
pthread cond broadcast 함수 가 특정한 조건 변수 에 막 힌 모든 스 레 드 를 깨 우기 때문에 이 스 레 드 가 깨 어 난 후에 해당 하 는 상호 배척 자 물 쇠 를 다시 경쟁 하기 때문에 pthread cond broadcast 함 수 를 조심해 야 합 니 다.
6. 조건 변수 pthread cond destroy 방출
#include
int pthread_cond_destroy(pthread_cond_t *cv);
반환 값: 함수 가 0 을 성공 적 으로 되 돌려 주 었 습 니 다. 다른 반환 값 은 모두 오 류 를 표시 합 니 다.
방출 조건 변수.
메모: 조건 변수 가 차지 하 는 공간 이 풀 리 지 않 았 습 니 다.
7. 분실 문 제 를 일깨우다
스 레 드 가 서로 배척 하 는 자 물 쇠 를 얻 지 못 했 을 때 pthread cond signal 또는 pthread cond broadcast 함 수 를 호출 하면 분실 문 제 를 일 으 킬 수 있 습 니 다.
잃 어 버 린 것 을 깨 우 는 것 은 종종 아래 의 상황 에서 발생 한다.
pthread cond signal 또는 pthread cond broadcast 함 수 를 호출 합 니 다.
다른 스 레 드 는 테스트 조건 변수 와 pthread cond wait 함수 사이 에 있 습 니 다.
스 레 드 가 없 는 상태 에서 기다 리 고 있 습 니 다.
마지막 으로 두 개의 직접 실행 할 수 있 는 프로그램 으로 조건 변수의 운행 과정 을 더욱 잘 이해 할 수 있다.
(메모: 전체 프로그램의 실행 과정 을 검증 하기 위해 printf 문 구 를 여러 개 추가 하 였 습 니 다)
/*    
                  :      。                                     ,
          。   ,             ,       ,                     。     
           ,                              。                     
  。    ,               。
cond1.c
[root@mashang smb]# gcc cond1.c -o cond1 -lpthread
[root@mashang smb]# ./cond1
*/ 
#include 
#include 
#include 

pthread_mutex_t count_lock;//   
pthread_cond_t count_nonzero;//   
unsigned count = 0;

void *decrement_count(void *arg)
{
    pthread_mutex_lock(&count_lock);//    :1  pthread_cond_wait     
    printf("decrement_count get count_lock
"); while(count == 0) { printf("decrement_count count == 0
"); printf("decrement_count before cond_wait
"); pthread_cond_wait(&count_nonzero, &count_lock);//2pthread_cond_wait , printf("decrement_count after cond_wait
"); } printf("tid1:count--
"); count = count - 1; printf("tid1:count= %d
", count); pthread_mutex_unlock(&count_lock); } void *increment_count(void *arg) { pthread_mutex_lock(&count_lock); // :1 ( ) printf("increment_count get count_lock
"); if(count == 0) { printf("increment_count before cond_signal
"); pthread_cond_signal(&count_nonzero); //2pthread_cond_signal printf("increment_count after cond_signal
"); } printf("tid2:count++
"); count = count + 1; printf("tid2:count= %d
", count); pthread_mutex_unlock(&count_lock);//3 . pthread_cond_wait 。 } int main(void) { pthread_t tid1, tid2; pthread_mutex_init(&count_lock, NULL); pthread_cond_init(&count_nonzero, NULL); pthread_create(&tid1, NULL, decrement_count, NULL); printf("tid1 decrement is created,begin sleep 2s
"); sleep(2); printf("after sleep 2s, start creat tid2 increment
"); pthread_create(&tid2, NULL, increment_count, NULL); printf("after tid2 increment is created,begin sleep 10s
"); sleep(5); printf("after sleep 5s,begin exit!
"); pthread_exit(0); return 0; }

두 번 째 루틴:
/*
cond2.c
[root@mashang smb]# gcc cond2.c -o cond2 -lpthread
[root@mashang smb]# ./cond2                             :
counter: 0                                         (1)    counter  0 (main)
main1: before creating thd1 decrement              (2)  thd1,      :
thd1 decrement get the lock                                   , counter 0,           (count_nonzero) .
thd1 decrement before cond_wait                                count_lock (wait       ,  signal         )
main2:thd1 is created, begin create thd2 increment (3)           ,       thrd2,      :
thd2 increment get the lock                                   , counter 0,        (count_nonzero)     thrd1
thd2 increment before cond_signal                               count_lock,thrd1     .【signal   ,wait         】
thd2 increment after  cond_signal                         thd2    ,count++,     
thd2 increment:counter = 1 
thd1 decrement after cond_wait                      thrd1       ,    counter    0,   0           count_nonzero   counter   1 .
thd1 decrement:counter = 0                                  .counter--     
main3:after thd1 and thd2, begin sleep and exit!   (4)   ,     main
*/ 

#include 
#include 
#include 

pthread_mutex_t counter_lock;
pthread_cond_t counter_nonzero;
int counter = 0;
int estatus = -1;

void *decrement_counter(void *argv);
void *increment_counter(void *argv);

int main(int argc, char **argv)
{
    printf("counter: %d
", counter); pthread_t thd1, thd2; int ret; printf("main1: before creating thd1 decrement
"); ret = pthread_create(&thd1, NULL, decrement_counter, NULL);// , pthread_cond_wait if(ret){ perror("del:/n"); return 1; } printf("main2:thd1 is created, begin create thd2 increment
"); ret = pthread_create(&thd2, NULL, increment_counter, NULL);// , pthread_cond_signal if(ret){ perror("inc: /n"); return 1; } printf("main3:after thd1 and thd2, begin sleep and exit!
"); sleep(3); return 0; } void *decrement_counter(void *argv) { pthread_mutex_lock(&counter_lock); printf("thd1 decrement get the lock
"); while(counter == 0) { printf("thd1 decrement before cond_wait
"); pthread_cond_wait(&counter_nonzero, &counter_lock); printf("thd1 decrement after cond_wait
"); } counter--; printf("thd1 decrement:counter = %d
", counter); pthread_mutex_unlock(&counter_lock); return &estatus; } void *increment_counter(void *argv) { pthread_mutex_lock(&counter_lock); printf("thd2 increment get the lock
"); if(counter == 0) { printf("thd2 increment before cond_signal
"); pthread_cond_signal(&counter_nonzero); printf("thd2 increment after cond_signal
"); } counter++; printf("thd2 increment:counter = %d
", counter); pthread_mutex_unlock(&counter_lock); return &estatus; }

좋은 웹페이지 즐겨찾기