1. 程式人生 > >linux多執行緒程式設計,替代sleep的幾種方式

linux多執行緒程式設計,替代sleep的幾種方式

我只想要程序的某個執行緒休眠一段時間的,可是用sleep()是將整個程序都休眠的,這個可能就達不到,我們想要的效果了。 目前我知道有三種方式:

1 usleep

   這個是輕量級的, 聽說能可一實現執行緒休眠, 我個人並不喜歡這種方式,所以我沒有驗證它的可行信(個人不推薦)。

2 select

   這個可以,我也用過這種方式, 它是在輪詢。

3  pthread_cond_timedwait

        採用pthread_cond_timedwait(pthread_cond_t* cond, pthread_mutex_t *mutex, const struct timespec *abstime)可以優雅的解決該問題,設定等待條件變數cond,如果超時,則返回;如果等待到條件變數cond,也返回。本文暫不將內部機理,僅演示一個demo。

       首先,看這段程式碼,thr_fn為一個執行緒函式:

#include <stdio.h>
#include <stdlib.h>

int flag = 1;
void * thr_fn(void * arg) {
  while (flag){
    printf("******\n");
    sleep(10);
  }
  printf("sleep test thread exit\n");
}
 
int main() {
  pthread_t thread;
  if (0 != pthread_create(&thread, NULL, thr_fn, NULL)) {
    printf("error when create pthread,%d\n", errno);
    return 1;
  }
 
  char c ;
  while ((c = getchar()) != 'q');
 
  printf("Now terminate the thread!\n");
  flag = 0;
  printf("Wait for thread to exit\n");
  pthread_join(thread, NULL);
  printf("Bye\n");
  return 0;
}
   輸入q後,需要等執行緒從sleep中醒來(由掛起狀態變為執行狀態),即最壞情況要等10s,執行緒才會被join。採用sleep的缺點:不能及時喚醒執行緒。
採用pthread_cond_timedwait函式實現的如下:
#include <stdio.h>
#include <sys/time.h>
#include <unistd.h>
#include <pthread.h>
#include <errno.h>
 
static pthread_t thread;
static pthread_cond_t cond;
static pthread_mutex_t mutex;
static int flag = 1;
 
void * thr_fn(void * arg) 
{
  struct timeval now;
  struct timespec outtime;
  pthread_mutex_lock(&mutex);
  while (flag) {
    printf("*****\n");
    gettimeofday(&now, NULL);
    outtime.tv_sec = now.tv_sec + 5;
    outtime.tv_nsec = now.tv_usec * 1000;
    pthread_cond_timedwait(&cond, &mutex, &outtime);
  }
  pthread_mutex_unlock(&mutex);
  printf("cond thread exit\n");
}
 
int main(void) 
{
  pthread_mutex_init(&mutex, NULL);
  pthread_cond_init(&cond, NULL);
  if (0 != pthread_create(&thread, NULL, thr_fn, NULL)) {
    printf("error when create pthread,%d\n", errno);
    return 1;
  }
  char c ;
  while ((c = getchar()) != 'q');
  printf("Now terminate the thread!\n");

  pthread_mutex_lock(&mutex);
  flag = 0;
  pthread_cond_signal(&cond);
  pthread_mutex_unlock(&mutex);
  printf("Wait for thread to exit\n");
  pthread_join(thread, NULL);
  printf("Bye\n");
  return 0;
}

        pthread_cond_timedwait()函式阻塞住呼叫該函式的執行緒,等待由cond指定的條件被觸發(pthread_cond_broadcast() or pthread_cond_signal())。

        當pthread_cond_timedwait()被呼叫時,呼叫執行緒必須已經鎖住了mutex。函式pthread_cond_timedwait()會對mutex進行【解鎖和執行對條件的等待】(原子操作)。這裡的原子意味著:解鎖和執行條件的等待是原則的,一體的。(In this case, atomically means with respect to the mutex andthe condition variable and other access by threads to those objectsthrough the pthread condition variable interfaces.)

       如果等待條件滿足或超時,或執行緒被取消,呼叫執行緒需要線上程繼續執行前先自動鎖住mutex,如果沒有鎖住mutex,產生EPERM錯誤。即,該函式返回時,mutex已經被呼叫執行緒鎖住。

       等待的時間通過abstime引數(絕對系統時間,過了該時刻就超時)指定,超時則返回ETIMEDOUT錯誤碼。開始等待後,等待時間不受系統時鐘改變的影響。

       儘管時間通過秒和納秒指定,系統時間是毫秒粒度的。需要根據排程和優先順序原因,設定的時間長度應該比預想的時間要多或者少點。可以通過使用系統時鐘介面gettimeofday()獲得timeval結構體。