一、C/C++多線程操作說明
C/C++多線程基本操作如下:
- 線程的建立結束
- 線程的互斥和同步
- 使用信号量控制線程
- 線程的基本屬性配置
在C/C++代碼編寫時,使用多線程機制,首先需要做的事情就是聲明引用,具體如下:
#include "pthread.h"
二、線程基本操作方法
基本線程操作:
- pthread_create():建立線程開始運作相關線程函數,運作結束則線程退出
- pthread_eixt():因為exit()是用來結束程序的,是以則需要使用特定結束線程的函數
- pthread_join():挂起目前線程,用于阻塞式地等待線程結束,如果線程已結束則立即傳回,0=成功
- pthread_cancel():發送終止信号給thread線程,成功傳回0,但是成功并不意味着thread會終止
- pthread_testcancel():在不包含取消點,但是又需要取消點的地方建立一個取消點,以便在一個沒有包含取消點的執行代碼線程中響應取消請求.
- pthread_setcancelstate():設定本線程對cancle線程的反應
- pthread_setcanceltype():設定取消狀态 繼續運作至下一個取消點再退出或者是立即執行取消動作
- pthread_setcancel():設定取消狀态
三、線程互斥與同步機制
基本的互斥與同步的操作方法:
- pthread_mutex_init():互斥鎖的初始化
- pthread_mutex_lock():鎖定互斥鎖,如果嘗試鎖定已經被上鎖的互斥鎖則阻塞至可用為止
- pthread_mutex_trylock():非阻塞的鎖定互斥鎖
- pthread_mutex_unlock():釋放互斥鎖
- pthread_mutex_destory():互斥鎖銷毀函數
四、多線程實踐
-
基本的線程及建立運作
下面的代碼是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時,直接傳回;
-
線程執行的互斥和同步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