线程是轻量级进程,创建线程的开销要比进程小得多,在大型程序中应用广泛。
线程一般在用户空间操作,pthread线程库是通用的POXIS标准。
【注意】:
线程如果调用exit(),会使整个进程退出。#include <pthread.h>int pthread_create( pthread_t * thread, pthread_attr_t * attr, void *(*start_routine)(void *), void * arg );参数: thread,线程标识符 attr,线程属性 start_routine, 线程入口函数 arg,传递给入口函数的参数返回值: 成功:0 出错:返回错误码void pthread_exit( void * retval );参数: retval,线程结束时的返回值,由其他线程使用pthread_join()获取 【注意】:如果返回变量,不用使用线程的局部变量,因为推出以后,线程的堆栈空间可能被占用,导致返回值的变化。 可以返回绝对值或者变量值。int pthread_join( pthread_t thread, void ** thread_return );参数: thread,要等待的线程标识符 thread_return, 被等待线程的返回值,实质是把 *thread_return = retval,其中retval是pthread_exit的指针,即传递了一个地址而已。可以利用传递的地址直接传递返回值,也可以利用变量传递,详见后面用例。 返回值: 成功:0 出错:返回错误码int pthread_cancel( pthread_t thread )参数: thread,要取消的线程标识符返回值: 成功:0 出错:返回错误码
//#define EXIT_USE_VER // 用变量返回,不可用线程自己的局部变量,因为退出以后有可能被复用
#define EXIT_USE_POINT // 用指针的赋值返回,适用于返回绝对值
#include <stdio.h> // printf#include <stdlib.h> // exit#include <unistd.h>#include <sys/types.h> // pid_t#include <fcntl.h>#include <pthread.h>
#define MAX_DELAY_SECONDS 10.0int rtn[3];
void fun_thread( int thread_no ){ unsigned char count=0; int delay_time=0;
printf("thread %d start.\r\n",thread_no); for(count=0;count<3;count++) { delay_time = (int)(rand() * MAX_DELAY_SECONDS/RAND_MAX)+1; sleep(delay_time); printf("thread %d loop %dst delay second %d\r\n",thread_no,count,delay_time); }#ifdef EXIT_USE_VER rtn[thread_no] = thread_no; pthread_exit((void*)&rtn[thread_no]); // 不同线程退出值不同,仅测试用#endif#ifdef EXIT_USE_POINT pthread_exit((void*)0xaa); // 可以返回绝对值 #endif}
int main(int args, char *argv[]){ unsigned thread_no; pthread_t thread[3];#ifdef EXIT_USE_VER int * thread_rtn;#endif #ifdef EXIT_USE_POINT void * thread_rtn;#endif
printf("start.\r\n"); for( thread_no=0; thread_no<3; thread_no++ ) { if( pthread_create(&thread[thread_no],NULL,fun_thread,(void*)thread_no) <0 ) printf("Create thread %d err.\r\n",thread_no); } // exit(0); 不能有此函数,否则创建完线程以后,exit会把本进程及内部所有线程一并退出
// 方法1:等待输入后结束 // getchar();
// 方法2:用pthread_join()等待所有线程结束 for( thread_no=0; thread_no<3; thread_no++ ) {#ifdef EXIT_USE_VER if( pthread_join(thread[thread_no], (void**)&thread_rtn) < 0 )#endif #ifdef EXIT_USE_POINT if( pthread_join(thread[thread_no], &thread_rtn) < 0 )#endif printf( "pthread_join:thread %d err.\r\n", thread_no); else#ifdef EXIT_USE_VER printf( "pthread_join:thread %d status %d.\r\n", thread_no,*thread_rtn);#endif #ifdef EXIT_USE_POINT printf( "pthread_join:thread %d status %d.\r\n", thread_no,(int)thread_rtn);#endif }
exit(0);}
$ ./example start.thread 2 start.thread 1 start.thread 0 start.thread 1 loop 0st delay second 4thread 0 loop 0st delay second 8thread 2 loop 0st delay second 9thread 2 loop 1st delay second 2thread 1 loop 1st delay second 8thread 2 loop 2st delay second 4thread 0 loop 1st delay second 10thread 1 loop 2st delay second 8thread 0 loop 2st delay second 3pthread_join:thread 0 status 170.pthread_join:thread 1 status 170.pthread_join:thread 2 status 170.
互斥锁适用于只有1个共享资源;
信号量适用多个共享资源的同步。
增加互斥锁,使原本独立的无序程序按设计预期运行
/* 9-1,pthread_mutex */
//#define EXIT_USE_VER // 用变量返回,不可用线程自己的局部变量,因为退出以后有可能被复用#define EXIT_USE_POINT // 用指针的赋值返回,适用于返回绝对值
#include <stdio.h> // printf#include <stdlib.h> // exit#include <unistd.h>#include <sys/types.h> // pid_t#include <fcntl.h>#include <pthread.h>
#define MAX_DELAY_SECONDS 10.0
#ifdef EXIT_USE_VER int rtn[3];#endif
pthread_mutex_t g_mutex;
void fun_thread( int thread_no ){ unsigned char count=0; int delay_time=0;
pthread_mutex_lock(&g_mutex); printf("thread %d start.\r\n",thread_no); for(count=0;count<3;count++) { delay_time = (int)(rand() * MAX_DELAY_SECONDS/RAND_MAX)+1; sleep(delay_time); printf("thread %d loop %dst delay second %d\r\n",thread_no,count,delay_time); } pthread_mutex_unlock(&g_mutex);#ifdef EXIT_USE_VER rtn[thread_no] = thread_no; pthread_exit((void*)&rtn[thread_no]); // 不同线程退出值不同,仅测试用#endif#ifdef EXIT_USE_POINT pthread_exit((void*)0); // 可以返回绝对值 #endif}
int main(int args, char *argv[]){ unsigned thread_no; pthread_t thread[3];#ifdef EXIT_USE_VER int * thread_rtn;#endif #ifdef EXIT_USE_POINT void * thread_rtn;#endif pthread_mutex_init(&g_mutex,NULL);
printf("start.\r\n"); for( thread_no=0; thread_no<3; thread_no++ ) { if( pthread_create(&thread[thread_no],NULL,fun_thread,(void*)thread_no) <0 ) printf("Create thread %d err.\r\n",thread_no); } // exit(0); 不能有此函数,否则创建完线程以后,exit会把本进程及内部所有线程一并退出
// 方法1:等待输入后结束 // getchar();
// 方法2:用pthread_join()等待所有线程结束 for( thread_no=0; thread_no<3; thread_no++ ) {#ifdef EXIT_USE_VER if( pthread_join(thread[thread_no], (void**)&thread_rtn) < 0 )#endif #ifdef EXIT_USE_POINT if( pthread_join(thread[thread_no], &thread_rtn) < 0 )#endif printf( "pthread_join:thread %d err.\r\n", thread_no); else#ifdef EXIT_USE_VER printf( "pthread_join:thread %d status %d.\r\n", thread_no,*thread_rtn);#endif #ifdef EXIT_USE_POINT printf( "pthread_join:thread %d status %d.\r\n", thread_no,(int)thread_rtn);#endif }
pthread_mutex_destroy(&g_mutex); exit(0);}
$ ./example start.thread 2 start.thread 2 loop 0st delay second 9thread 2 loop 1st delay second 4thread 2 loop 2st delay second 8thread 1 start.thread 1 loop 0st delay second 8thread 1 loop 1st delay second 10thread 1 loop 2st delay second 2thread 0 start.thread 0 loop 0st delay second 4thread 0 loop 1st delay second 8thread 0 loop 2st delay second 3pthread_join:thread 0 status 0.pthread_join:thread 1 status 0.pthread_join:thread 2 status 0.
互斥流程
#include <semaphore.h>int sem_init( sem_t *sem, int pshared, unsigned int value ); // 创建信号量,并初始化它的值参数: sem,信号量指针 pshared,决定信号量能在几个进程间共享,linux不支持,只能用0; value,信号量初始值返回值: 成功:0 出错:-1int sem_wait( sem_t *sem ); // P操作,阻塞int sem_trywait( sem_t *sem ); // P操作,不阻塞int sem_post( sem_t *sem ); // V操作int sem_getvalue(set_t * sem ); // 得到信号量的值int sem_destroy(sem_t * sem ); // 删除信号量参数: sem,信号量指针返回值: 成功:0 出错:-1
用信号量实现3个进程的有序执行,倒着来,2->1->0
/* 9-3,sem */
#include <stdio.h> // printf#include <stdlib.h> // exit#include <unistd.h>#include <sys/types.h> // pid_t#include <fcntl.h>#include <pthread.h> #include <semaphore.h>
#define MAX_DELAY_SECONDS 2.0
sem_t g_sem[3];
void fun_thread( int thread_no ){ unsigned char count=0; int delay_time=0;
sem_wait(&g_sem[thread_no]);
printf("thread %d start.\r\n",thread_no); for(count=0;count<3;count++) { delay_time = (int)(rand() * MAX_DELAY_SECONDS/RAND_MAX)+1; sleep(delay_time); printf("thread %d loop %dst delay second %d\r\n",thread_no,count,delay_time); } if( thread_no!=0 ) sem_post(&g_sem[thread_no-1]); pthread_exit((void*)0); // 可以返回绝对值 }
int main(int args, char *argv[]){ unsigned thread_no; pthread_t thread[3]; void * thread_rtn;
printf("start.\r\n");
sem_init(&g_sem[0], 0,0); sem_init(&g_sem[1], 0,0); sem_init(&g_sem[2], 0,1); // 允许2先运行
for( thread_no=0; thread_no<3; thread_no++ ) { if( pthread_create(&thread[thread_no],NULL,fun_thread,(void*)thread_no) <0 ) printf("Create thread %d err.\r\n",thread_no); } // exit(0); 不能有此函数,否则创建完线程以后,exit会把本进程及内部所有线程一并退出
// 方法1:等待输入后结束 // getchar();
// 方法2:用pthread_join()等待所有线程结束 for( thread_no=0; thread_no<3; thread_no++ ) { if( pthread_join(thread[thread_no], &thread_rtn) < 0 ) printf( "pthread_join:thread %d err.\r\n", thread_no); else printf( "pthread_join:thread %d status %d.\r\n", thread_no,(int)thread_rtn); } sem_destroy(&g_sem[0]); sem_destroy(&g_sem[1]); sem_destroy(&g_sem[2]); exit(0);}
$ ./example start.thread 2 start.thread 2 loop 0st delay second 2thread 2 loop 1st delay second 1thread 2 loop 2st delay second 2thread 1 start.thread 1 loop 0st delay second 2thread 1 loop 1st delay second 2thread 1 loop 2st delay second 1thread 0 start.thread 0 loop 0st delay second 1thread 0 loop 1st delay second 2thread 0 loop 2st delay second 1pthread_join:thread 0 status 0.pthread_join:thread 1 status 0.pthread_join:thread 2 status 0.
转载于:https://www.cnblogs.com/liuwanpeng/p/6652327.html