天天看點

C/C++多線程操作

一、C/C++多線程操作說明

C/C++多線程基本操作如下:

  • 線程的建立結束
  • 線程的互斥和同步
  • 使用信号量控制線程
  • 線程的基本屬性配置

在C/C++代碼編寫時,使用多線程機制,首先需要做的事情就是聲明引用,具體如下:

#include "pthread.h"      

二、線程基本操作方法

基本線程操作:

  1. pthread_create():建立線程開始運作相關線程函數,運作結束則線程退出
  2. pthread_eixt():因為exit()是用來結束程序的,是以則需要使用特定結束線程的函數
  3. pthread_join():挂起目前線程,用于阻塞式地等待線程結束,如果線程已結束則立即傳回,0=成功
  4. pthread_cancel():發送終止信号給thread線程,成功傳回0,但是成功并不意味着thread會終止
  5. pthread_testcancel():在不包含取消點,但是又需要取消點的地方建立一個取消點,以便在一個沒有包含取消點的執行代碼線程中響應取消請求.
  6. pthread_setcancelstate():設定本線程對cancle線程的反應
  7. pthread_setcanceltype():設定取消狀态 繼續運作至下一個取消點再退出或者是立即執行取消動作
  8. pthread_setcancel():設定取消狀态

三、線程互斥與同步機制

基本的互斥與同步的操作方法:

  1. pthread_mutex_init():互斥鎖的初始化
  2. pthread_mutex_lock():鎖定互斥鎖,如果嘗試鎖定已經被上鎖的互斥鎖則阻塞至可用為止
  3. pthread_mutex_trylock():非阻塞的鎖定互斥鎖
  4. pthread_mutex_unlock():釋放互斥鎖
  5. pthread_mutex_destory():互斥鎖銷毀函數

四、多線程實踐

  1. 基本的線程及建立運作

    下面的代碼是C/C++開發的基本的線程的運作,使用的就是最基本的pthread.h:

/* thread.c */
#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
 
#define THREAD_NUMBER       3                 /*線程數*/
#define REPEAT_NUMBER       5                 /*每個線程中的小任務數*/
#define DELAY_TIME_LEVELS  10.0             /*小任務之間的最大時間間隔*/
//
void *thrd_func(void *arg) { 
    /* 線程函數例程 */
    int thrd_num = (int)arg;
    int delay_time = 0;
    int count = 0;
    printf("Thread %d is starting\n", thrd_num);
    for (count = 0; count < REPEAT_NUMBER; count++) {
        delay_time = (int)(rand() * DELAY_TIME_LEVELS/(RAND_MAX)) + 1;
        sleep(delay_time);
        printf("\tThread %d: job %d delay = %d\n", thrd_num, count, delay_time);
    }
 
    printf("Thread %d finished\n", thrd_num);
    pthread_exit(NULL);
}
 
int main(void) {
     pthread_t thread[THREAD_NUMBER];
     int no = 0, res;
     void * thrd_ret;
     srand(time(NULL));    
     for (no = 0; no < THREAD_NUMBER; no++) {
          /* 建立多線程 */
          res = pthread_create(&thread[no], NULL, thrd_func, (void*)no);
          if (res != 0) {
               printf("Create thread %d failed\n", no);
               exit(res);
          }
     }
 
     printf("Create treads success\n Waiting for threads to finish...\n");
     for (no = 0; no < THREAD_NUMBER; no++) {
          /* 等待線程結束 */
          res = pthread_join(thread[no], &thrd_ret);
          if (!res) {
            printf("Thread %d joined\n", no);
          } else {
            printf("Thread %d join failed\n", no);
          }
     }
     return 0;        
}      

例程中循環3次建立3條線程,并且使用pthread_join函數依次等待線程結束;

線程中使用rand()擷取随機值随機休眠5次,随意會出現後執行的線程先執行完成;

運作結果:

$ gcc thread.c -lpthread
$ ./a.out 
Create treads success
 Waiting for threads to finish...
Thread 0 is starting
Thread 1 is starting
Thread 2 is starting
Thread 1: job 0 delay = 2
Thread 1: job 1 delay = 2
Thread 0: job 0 delay = 8
Thread 2: job 0 delay = 10
Thread 2: job 1 delay = 3
Thread 1: job 2 delay = 10
Thread 0: job 1 delay = 8
Thread 0: job 2 delay = 3
Thread 0: job 3 delay = 1
Thread 2: job 2 delay = 8
Thread 1: job 3 delay = 8
Thread 1: job 4 delay = 1
Thread 1 finished
        Thread 2: job 3 delay = 6
        Thread 0: job 4 delay = 7
Thread 0 finished
Thread 0 joined
Thread 1 joined
        Thread 2: job 4 delay = 10
Thread 2 finished
Thread 2 joined      

可以看到,線程1先于線程0執行,但是pthread_join的調用時間順序,先等待線程0執行;

由于線程1已經早結束,是以線程0被pthread_join等到的時候,線程1已結束,就在等待到線程1時,直接傳回;

  1. 線程執行的互斥和同步pthread_mutex_lock

    下面我們在上面的程式中增加互斥鎖:

/*thread_mutex.c*/
#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
#include <unistd.h>
 
#define THREAD_NUMBER        3            /* 線程數 */
#define REPEAT_NUMBER        3            /* 每個線程的小任務數 */
#define DELAY_TIME_LEVELS 10.0         /*小任務之間的最大時間間隔*/
pthread_mutex_t mutex;
 
void *thrd_func(void *arg) {
     int thrd_num = (int)arg;
     int delay_time = 0, count = 0;
     int res;
     /* 互斥鎖上鎖 */
     res = pthread_mutex_lock(&mutex);
     if (res) {
          printf("Thread %d lock failed\n", thrd_num);
          pthread_exit(NULL);
     }
     printf("Thread %d is starting\n", thrd_num);
     for (count = 0; count < REPEAT_NUMBER; count++) {          
         delay_time = (int)(rand() * DELAY_TIME_LEVELS/(RAND_MAX)) + 1;
         sleep(delay_time);
         printf("\tThread %d: job %d delay = %d\n", 
                                      thrd_num, count, delay_time);
     }
     printf("Thread %d finished\n", thrd_num);
     /****互斥鎖解鎖***/
     pthread_mutex_unlock(&mutex);
     pthread_exit(NULL);
}
 
int main(void) {
     pthread_t thread[THREAD_NUMBER];
     int no = 0, res;
     void * thrd_ret;
 
     srand(time(NULL));
     /* 互斥鎖初始化 */
     pthread_mutex_init(&mutex, NULL);
     for (no = 0; no < THREAD_NUMBER; no++) {
          res = pthread_create(&thread[no], NULL, thrd_func, (void*)no);
          if (res != 0) {
              printf("Create thread %d failed\n", no);
              exit(res);
          }
     }     
     printf("Create treads success\n Waiting for threads to finish...\n");
     for (no = 0; no < THREAD_NUMBER; no++) {
          res = pthread_join(thread[no], &thrd_ret);
          if (!res) {
                printf("Thread %d joined\n", no);
          } else  {
              printf("Thread %d join failed\n", no);
          }
     }   
     pthread_mutex_destroy(&mutex);          
     return 0;        
}      

在上面的例程中直接添加同步鎖pthread_mutex_t;

線上程中加入,程式在執行線程程式時,調用pthread_mutex_lock上鎖,發現上鎖時候後進入等待,等待鎖再次釋放後重新上鎖;

是以線程程式加載到隊列中等待,等待成功上鎖後繼續執行程式代碼;

Create treads success
 Waiting for threads to finish...
Thread 0 is starting
    Thread 0: job 0 delay = 7
    Thread 0: job 1 delay = 2
    Thread 0: job 2 delay = 9
Thread 0 finished
Thread 2 is starting
Thread 0 joined
    Thread 2: job 0 delay = 6
    Thread 2: job 1 delay = 7
    Thread 2: job 2 delay = 10
Thread 2 finished
Thread 1 is starting
    Thread 1: job 0 delay = 3
    Thread 1: job 1 delay = 5
    Thread 1: job 2 delay = 2
Thread 1 finished
Thread 1 joined
Thread 2 joined      

繼續閱讀