多线程程序的设计详解
进程与线程:
进程是一个拷贝的流程,需要更大的系统开销。具有互斥性,某一进程使用着资源其他均需等待。
线程就是把一个进程分为多片,每一片都是一个独立的流程,线程相较于进程没有拷贝这些额外的系统开销。他们共享着进程的代码段、数据段,但每个线程都有属于自己的堆、栈段。所以并发程序设计师常用多线程实现!
多线程程序设计基础函数:
1)创建线程
int pthread_create(pthread_t *restrict tidp, //存储新创建线程的id,指针类型 const pthread_attr_t *restrict attr, //创建线程的属性,一般NULL void *(*start_rtn)(void), //线程的执行函数的入口地址 void *restrict arg); //执行函数的参数,一般NULL Returns: 0 if OK, error number on failure
eg: pthread_create(&thread[0], NULL, worker1, NULL);//worker1:线程的入口函数
2)等待线程
int pthread_join (pthread_t thread,void **retval);//要等待线程的id 保存线程退出时的状态,一般为NULL
Returns: 0 if OK, error number on failure
eg: pthread_join(thread[0], NULL);
3)退出线程
void pthread_exit (void * retval); //保存退出状态,一般NULL
eg: pthread_exit(NULL); //退出线程
--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
多线程互斥设计:
实际中多线程同样具有互斥性,会同时访问同一资源->互斥锁(信号量flag)
pthread_mutex_t mut;//定义一个互斥锁
下列函数成功返回0!
1)初始化互斥锁 eg: pthread_mutex_init(&mut,NULL);
int pthread_mutex_init( pthread_mutex_t* mut, ~ attr); //互斥锁的指针 指定互斥锁属性NULL
2)锁住互斥锁 eg: pthread_mutex_lock(&mut);
int pthread_mutex_lock(pthread_mutex_t* mut); //指明需要锁住的互斥锁
3)解开互斥锁 eg: pthread_mutex_unlock(&mut);
int pthread_mutex_unlock(pthread_mutex_t* mut); //指明需要解开的互斥锁
一般多线程与互斥锁配合使用,多线程共用全局变量,每个任务函数拥有独自的堆栈,各自并行运行不打扰!
主程序中 : 初始化互斥锁->创建多个线程(括入了线程函数)->等待多个线程结束->return 0; 此时多线程的任务函数已在后台并发运行,等待任务函数完成后程序退出;
线程任务函数中:每个线程任务函数->使用各自的堆栈空间->锁住互斥锁->共用进程所有资源->解开互斥锁->完成,退出线程; 多线程并发性的体现。
--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
多线程同步设计:
多个线程按照规定要求的顺序来执行,即为线程同步。 设规定顺序:线程A->线程B->任务完成
同步函数->相当于开关信号量
设定外部全局变量: pthread_cond_t cond_ready = PTHREAD_COND_INITIALIZER;
1)条件成熟函数
pthread_cond_signal(&cond_ready); //线程A->调用此,运行后及条件成熟
2)等待条件成熟
pthread_cond_wait(&cond_ready,&mut); //线程B->等待状态 本线程互斥锁信号量
多线程互斥+同步函数=多线程同步
主程序中 : 与多线程互斥相同;
线程任务函数中:与多线程互斥前后部分相同,仅仅一个地方!锁住互斥锁->共用进程所有资源->各线程条件设定,实现顺序功能->解开互斥锁-> ;
线程A满足时,运行条件成熟函数pthread_cond_signal;线程B未等到线程A完成设定要求是,运行pthread_cond_wait一直等待。
/*多线程互斥*/ #include <pthread.h> #include <stdio.h> pthread_t thread[2];//保存线程1和2的id int number = 0; pthread_mutex_t mut;//定义一个互斥锁 void * worker1() { int i = 0; printf("I am worker1!\n"); for(i=0;i<10;i++) { pthread_mutex_lock(&mut);//加锁 number++; pthread_mutex_unlock(&mut);//解锁 printf("worker1 number is %d\n",number); sleep(1); } pthread_exit(NULL); //退出线程 } void * worker2() { int i = 0; printf("I am worker2!\n"); for(i=0;i<10;i++) { pthread_mutex_lock(&mut);//加锁 number++; pthread_mutex_unlock(&mut);//解锁 printf("worker2 number is %d\n",number); sleep(1); } pthread_exit(NULL); //退出线程 } int main() { pthread_mutex_init(&mut,NULL);//锁的初始化,默认属性 /*创建工人1线程*/ pthread_create(&thread[0], NULL, worker1, NULL);//worker1:线程的入口函数 /*创建工人2线程*/ pthread_create(&thread[1], NULL, worker2, NULL); /*等待工人1线程的结束*/ pthread_join(thread[0], NULL); /*等待工人2线程的结束*/ pthread_join(thread[1], NULL); return 0; }
/*多线程同步*/ #include <pthread.h> #include <stdio.h> pthread_t thread[2]; int number = 0; pthread_mutex_t mut; pthread_cond_t cond_ready=PTHREAD_COND_INITIALIZER; void * studentA() { int i; for(i=0;i<5;i++) { pthread_mutex_lock(&mut); /*扫一次地*/ number++; if (number >=5) { printf("student A has finished his work!\n"); /*通知B同学*/ pthread_cond_signal(&cond_ready); } pthread_mutex_unlock(&mut); /*休息1秒钟*/ sleep(1); } /*退出*/ pthread_exit(NULL); } void * studentB() { pthread_mutex_lock(&mut); if(number<5)/*判断A同学是否已经扫完5次地*/ pthread_cond_wait(&cond_ready,&mut); /*拖地*/ number = 0; pthread_mutex_unlock(&mut); printf("student B has finished his work!\n"); /*退出*/ pthread_exit(NULL); } int main() { /*初始化互斥锁*/ pthread_mutex_init(&mut,NULL); /*创建A同学线程*/ pthread_create(&thread[0], NULL, studentA, NULL); /*创建B同学线程*/ pthread_create(&thread[1], NULL, studentB, NULL); /*等待A同学线程结束*/ pthread_join(thread[0], NULL); /*等待B同学线程结束*/ pthread_join(thread[1], NULL); }