进程创建,进程的调度较为消耗硬件资源,进程切换时会涉及到多个硬件资源的切换c++
线程本质是带有时间片的函数(模块化代码,多个函数相对独立)编程
线程共享资源:
共享进程空间0~3G空间
PIDide
线程独立的资源:
线程的栈区独立
PC指针
线程errno独立
线程编号相互独立模块化
注:不能返回线程空间内的地址函数
安装线程库:
sudo apt-get install manpages-posix-dev
sudo apt-get install manpages-posixpost
线程编程:
注:
1.添加#include <pthread.h>
2.编译时连接线程库 -lpthread
3.线程中慎用exit函数学习
线程建立:本质是线程调用
pthread_create
int pthread_create(pthread_t *thread, const pthread_attr_t *attr,void *(*start_routine) (void *), void *arg);
参数:1.pthread_create成功执行时能够获取线程编号 准备pthread_t 变量 取地址放入;2.线程属性设置 填NULL表示默认属性
3.被调用的线程函数的入口地址 void * 线程名(void *);4.用于给第三个参数传参 不须要填NULL
功能:线程调用函数
返回值:成功返回0,失败返回错误号,并设置errno号ui
线程阻塞函数 相似进程中的waitpid(pid)
pthread_join
int pthread_join(pthread_t thread, void **retval);
功能:阻塞等待指定线程退出
参数:1.线程号 2.接收pthread_exit返回的信息 定义一个void* p &p放入,不关心填NULL
返回值:成功返货0,失败返回errno号spa
线程退出 相似进程中的exit
pthread_exit
void pthread_exit(void *retval);
功能:结束调用的线程,返回的一个地址(用于记录信息的首地址,不使用填NULL)线程
线程取消
pthread_cancel
int pthread_cancel(pthread_t thread);
功能:将指定线程退出
1 #include <stdio.h> 2 #include <pthread.h> 3 #include <stdlib.h> 4 pthread_t tid1,tid2; 5 int i = 0; 6 int a,b; 7 8 9 void *fun_a(void *arg) 10 { 11 while(1) 12 { 13 i++; 14 a = i; 15 b = a; 16 } 17 pthread_exit(NULL); 18 } 19 20 void *fun_b(void *arg) 21 { 22 while(1) 23 { 24 if(a != b) 25 { 26 printf("i:%d a:%d b:%d\n",i,a,b); 27 } 28 } 29 pthread_exit(NULL); 30 } 31 32 int main(int argc, const char *argv[]) 33 { 34 int ret = 0; 35 ret = pthread_create(&tid1,NULL,fun_a,NULL); 36 if(ret != 0) 37 { 38 fprintf(stderr,"fail to create pthread1:%d\n",ret); 39 exit(1); 40 } 41 pthread_create(&tid2,NULL,fun_b,NULL); 42 43 44 pthread_join(tid1,NULL); 45 pthread_join(tid2,NULL); 46 47 return 0; 48 }
1 #include <stdio.h> 2 #include <pthread.h> 3 4 pthread_t tid1,tid2; 5 6 //线程A: 7 void *fun1(void * arg) 8 { 9 if(arg != NULL) 10 { 11 printf("pthread1_arg:%s\n",(char *)arg); 12 } 13 printf("i'm pthread_1!\n"); 14 pthread_exit("hehehe"); 15 } 16 17 18 //线程B: 19 void *fun2(void * arg) 20 { 21 if(arg != NULL) 22 { 23 printf("pthread2_arg:%s\n",(char *)arg); 24 } 25 printf("i'm pthread_2!\n"); 26 pthread_exit("heiheihei"); 27 } 28 29 30 31 int main(int argc, const char *argv[]) 32 { 33 34 char *s1 = "zhangyaqi meimeimei"; 35 char *s2 = "jiangtiti meimeimei"; 36 //线程调用 37 pthread_create(&tid1,NULL,fun1,s1); 38 pthread_create(&tid2,NULL,fun2,s2); 39 40 char *ret1 = NULL; 41 char *ret2 = NULL; 42 43 //阻塞主线程等待全部子线程退出 44 pthread_join(tid1,(void **)&ret1); 45 pthread_join(tid2,(void **)&ret2); 46 47 printf("pthread1_exit:%s\n",ret1); 48 printf("pthread2_exit:%s\n",ret2); 49 50 51 return 0; 52 }
1 #include <stdio.h> 2 #include <pthread.h> 3 #include <unistd.h> 4 5 pthread_t tid1,tid2,tid3; 6 7 //线程A 8 void *fun_a(void *arg) 9 { 10 while(1) 11 { 12 printf("i'm pthread_a!\n"); 13 sleep(1); 14 } 15 pthread_exit(NULL); 16 } 17 //线程B 18 void *fun_b(void *arg) 19 { 20 while(1) 21 { 22 printf("i'm pthread_b!\n"); 23 sleep(1); 24 } 25 pthread_exit(NULL); 26 } 27 //线程C 28 void *fun_c(void *arg) 29 { 30 sleep(10); 31 pthread_cancel(tid1); 32 pthread_cancel(tid2); 33 34 pthread_exit(NULL); 35 } 36 37 int main(int argc, const char *argv[]) 38 { 39 pthread_create(&tid1,NULL,fun_a,NULL); 40 pthread_create(&tid2,NULL,fun_b,NULL); 41 pthread_create(&tid3,NULL,fun_c,NULL); 42 43 pthread_join(tid1,NULL); 44 pthread_join(tid2,NULL); 45 pthread_join(tid3,NULL); 46 47 48 49 return 0; 50 }
线程同步和互斥:
同步:自己也是一种特殊的互斥
互斥:
1.全局变量:
作同步没有问题,互斥时可能会出现问题(最好不要用全局变量作互斥)
1 #include <stdio.h> 2 #include <pthread.h> 3 4 pthread_t tida,tidb,tidc; 5 int leda,ledb,ledc; 6 7 void *pthread_a(void *arg) 8 { 9 while(1) 10 { 11 if(leda == 1) 12 { 13 leda--; 14 printf("i'm pthread_a!\n"); 15 ledb++; 16 } 17 } 18 pthread_exit(NULL); 19 } 20 21 void *pthread_b(void *arg) 22 { 23 while(1) 24 { 25 if(ledb == 1) 26 { 27 ledb--; 28 printf("i'm pthread_b!\n"); 29 ledc++; 30 } 31 } 32 pthread_exit(NULL); 33 } 34 35 void *pthread_c(void *arg) 36 { 37 while(1) 38 { 39 if(ledc == 1) 40 { 41 ledc--; 42 printf("i'm pthread_c!\n"); 43 leda++; 44 } 45 } 46 pthread_exit(NULL); 47 } 48 49 50 51 int main(int argc, const char *argv[]) 52 { 53 //初始化灯 54 leda = 1; 55 ledb = 0; 56 ledc = 0; 57 58 pthread_create(&tida,NULL,pthread_a,NULL); 59 pthread_create(&tidb,NULL,pthread_b,NULL); 60 pthread_create(&tidc,NULL,pthread_c,NULL); 61 62 pthread_join(tida,NULL); 63 pthread_join(tidb,NULL); 64 pthread_join(tidc,NULL); 65 66 return 0; 67 }
1 #include <stdio.h> 2 #include <pthread.h> 3 #include <stdlib.h> 4 pthread_t tid1,tid2; 5 volatile int flag; 6 7 8 void *fun_a(void *arg) 9 { 10 while(1) 11 { 12 if(flag == 1) 13 { 14 flag--; 15 printf("i'm pthread_a!\n"); 16 printf("aaaaaaaaaaaaaa\n"); 17 flag++; 18 } 19 } 20 pthread_exit(NULL); 21 } 22 23 void *fun_b(void *arg) 24 { 25 while(1) 26 { 27 if(flag == 1) 28 { 29 flag--; 30 printf("i'm pthread_b!\n"); 31 printf("bbbbbbbbbbbbbb\n"); 32 flag++; 33 } 34 } 35 pthread_exit(NULL); 36 } 37 38 int main(int argc, const char *argv[]) 39 { 40 flag = 1; 41 int ret = 0; 42 ret = pthread_create(&tid1,NULL,fun_a,NULL); 43 if(ret != 0) 44 { 45 fprintf(stderr,"fail to create pthread1:%d\n",ret); 46 exit(1); 47 } 48 pthread_create(&tid2,NULL,fun_b,NULL); 49 50 51 pthread_join(tid1,NULL); 52 pthread_join(tid2,NULL); 53 54 return 0; 55 }
2.信号量
sem_init 信号量初始化
int sem_init(sem_t *sem, int pshared, unsigned int value);
参数:1.sem_init成功执行时获取对应的信号量编号; 2.决定该信号量用于线程仍是进程 填0表示用于线程;3.信号量的初始值
功能:建立信号量,并设置初始值
返回值:成功返回0,失败返回-1,并设置errno号
sem_wait p操做
int sem_wait(sem_t *sem);
参数:1.信号量地址
功能:对指定信号量执行-1操做,若是信号量值为0,则阻塞等待信号量值>0
返回值:成功返回0,失败返回-1,并设置errno号
sem_post v操做
int sem_post(sem_t *sem);
参数:1.信号量地址
功能:对指定信号量进行+1操做
返回值:成功返回0,失败返回-1,并设置errno号
sem_destroy
int sem_destroy(sem_t *sem);
参数:1.信号量的地址
功能:销毁指定信号量
返回值:成功返回0,失败返回-1,并设置errno号
1 #include <stdio.h> 2 #include <semaphore.h> 3 #include <pthread.h> 4 5 sem_t sem1,sem2,sem3; 6 pthread_t tid1,tid2,tid3; 7 8 void *pthread_a(void *arg) 9 { 10 while(1) 11 { 12 sem_wait(&sem1); 13 printf("i'm pthread_a!\n"); 14 sem_post(&sem2); 15 } 16 pthread_exit(NULL); 17 } 18 19 void *pthread_b(void *arg) 20 { 21 while(1) 22 { 23 sem_wait(&sem2); 24 printf("i'm pthread_b!\n"); 25 sem_post(&sem3); 26 } 27 pthread_exit(NULL); 28 } 29 30 void *pthread_c(void *arg) 31 { 32 while(1) 33 { 34 sem_wait(&sem3); 35 printf("i'm pthread_c!\n"); 36 sem_post(&sem1); 37 } 38 pthread_exit(NULL); 39 } 40 41 int main(int argc, const char *argv[]) 42 { 43 //初始化 44 sem_init(&sem1,0,1); 45 sem_init(&sem2,0,0); 46 sem_init(&sem3,0,0); 47 48 //调用线程 49 pthread_create(&tid1,NULL,pthread_a,NULL); 50 pthread_create(&tid2,NULL,pthread_b,NULL); 51 pthread_create(&tid3,NULL,pthread_c,NULL); 52 53 54 55 //线程阻塞 56 pthread_join(tid1,NULL); 57 pthread_join(tid2,NULL); 58 pthread_join(tid3,NULL); 59 60 61 //销毁信号量 62 sem_destroy(&sem1); 63 sem_destroy(&sem2); 64 sem_destroy(&sem3); 65 return 0; 66 }
1 #include <stdio.h> 2 #include <pthread.h> 3 #include <semaphore.h> 4 5 pthread_t tid1,tid2,tid3; 6 sem_t sem1; 7 8 9 void *pthread_a(void *arg) 10 { 11 while(1) 12 { 13 sem_wait(&sem1);//阻塞等待 若是sem>0 则-1 14 printf("i'm pthread_a!\n"); 15 sem_post(&sem1);//sem +1 16 } 17 pthread_exit(NULL); 18 } 19 20 21 void *pthread_b(void *arg) 22 { 23 while(1) 24 { 25 sem_wait(&sem1); 26 printf("i'm pthread_b!\n"); 27 sem_post(&sem1); 28 } 29 pthread_exit(NULL); 30 } 31 32 33 void *pthread_c(void *arg) 34 { 35 while(1) 36 { 37 sem_wait(&sem1); 38 printf("i'm pthread_c!\n"); 39 sem_post(&sem1); 40 } 41 pthread_exit(NULL); 42 } 43 44 45 int main(int argc, const char *argv[]) 46 { 47 48 //建立并初始化信号量 49 sem_init(&sem1,0,1); 50 51 pthread_create(&tid1,NULL,pthread_a,NULL); 52 pthread_create(&tid2,NULL,pthread_b,NULL); 53 pthread_create(&tid3,NULL,pthread_c,NULL); 54 55 56 pthread_join(tid1,NULL); 57 pthread_join(tid2,NULL); 58 pthread_join(tid3,NULL); 59 60 //销毁信号量 61 sem_destroy(&sem1); 62 63 64 return 0; 65 }
3.互斥锁 实现代码块之间的互斥
pthread_mutex_init 建立锁
int pthread_mutex_init(pthread_mutex_t *restrict mutex,const pthread_mutexattr_t *restrict attr);
参数:1.当pthread_mutex_init成功执行后获取锁号 2.锁的属性 填NULL,按默认属性
返回值:成功返回0,失败返回错误号
pthread_mutex_lock 上锁
int pthread_mutex_lock(pthread_mutex_t *mutex);
参数:1.锁号的地址
返回值:成功返回0,失败返回错误号
pthread_mutex_unlock 解锁
int pthread_mutex_unlock(pthread_mutex_t *mutex);
参数:1.锁号的地址
返回值:成功返回0,失败返回错误号
pthread_mutex_destroy 销毁锁
int pthread_mutex_destroy(pthread_mutex_t *mutex);
参数:1.锁号的地址
返回值:成功返回0,失败返回错误号
1 #include <stdio.h> 2 #include <pthread.h> 3 #include <stdlib.h> 4 pthread_t tid1,tid2; 5 int i = 0; 6 int a,b; 7 pthread_mutex_t lock; 8 9 void *fun_a(void *arg) 10 { 11 while(1) 12 { 13 //上锁 14 pthread_mutex_lock(&lock); 15 i++; 16 a = i; 17 b = a; 18 //解锁 19 pthread_mutex_unlock(&lock); 20 } 21 pthread_exit(NULL); 22 } 23 24 void *fun_b(void *arg) 25 { 26 while(1) 27 { 28 pthread_mutex_lock(&lock); 29 if(a != b) 30 { 31 printf("i:%d a:%d b:%d\n",i,a,b); 32 } 33 pthread_mutex_unlock(&lock); 34 } 35 pthread_exit(NULL); 36 } 37 38 int main(int argc, const char *argv[]) 39 { 40 //建立锁 41 pthread_mutex_init(&lock,NULL); 42 43 int ret = 0; 44 ret = pthread_create(&tid1,NULL,fun_a,NULL); 45 if(ret != 0) 46 { 47 fprintf(stderr,"fail to create pthread1:%d\n",ret); 48 exit(1); 49 } 50 pthread_create(&tid2,NULL,fun_b,NULL); 51 52 53 pthread_join(tid1,NULL); 54 pthread_join(tid2,NULL); 55 56 //销毁锁 57 pthread_mutex_destroy(&lock); 58 return 0; 59 }
4.条件变量
pthread_cond_init 条件变量的初始化
int pthread_cond_init(pthread_cond_t *restrict cond,const pthread_condattr_t *restrict attr);
参数:1.pthread_cond_init成功执行时获取条件变量编号 2.条件变量的属性 填NULL默认属性
返回值:成功返回0,失败返回错误号
pthread_cond_signal
int pthread_cond_signal(pthread_cond_t *cond);
pthread_cond_broadcast
int pthread_cond_broadcast(pthread_cond_t *cond);
pthread_cond_wait 解锁->等待->上锁
int pthread_cond_wait(pthread_cond_t *restrict cond,pthread_mutex_t *restrict mutex);
参数:1.条件变量编号 2.锁号
返回值:成功返回0,失败返回错误号
pthread_cond_destroy 销毁信号量
int pthread_cond_destroy(pthread_cond_t *cond);
参数:1.条件变量编号的地址
返回值:成功返回0,失败返回错误号
1 #include <stdio.h> 2 #include <pthread.h> 3 #include <strings.h> 4 #include <stdlib.h> 5 6 pthread_mutex_t lock; 7 8 pthread_cond_t cond; 9 10 pthread_t tid1,tid2,tid3; 11 12 char buf[128]; 13 14 //线程A 15 void *fun_a(void *arg) 16 { 17 while(1) 18 { 19 bzero(buf,sizeof(buf)); 20 printf("(pthread_a)please input something:\n"); 21 fgets(buf,sizeof(buf),stdin); 22 //pthread_cond_signal(&cond); 23 pthread_cond_broadcast(&cond); 24 sleep(1); 25 } 26 pthread_exit(NULL); 27 } 28 29 //线程B 30 void *fun_b(void *arg) 31 { 32 while(1) 33 { 34 pthread_mutex_lock(&lock); 35 // printf("i'm pthread_b!\n"); 36 37 pthread_cond_wait(&cond,&lock); 38 printf("pthread_b buf:%s\n",buf); 39 if(strncmp(buf,"quit",4) == 0) 40 { 41 exit(0); 42 } 43 44 pthread_mutex_unlock(&lock); 45 } 46 pthread_exit(NULL); 47 } 48 49 50 //线程C 51 void *fun_c(void *arg) 52 { 53 while(1) 54 { 55 pthread_mutex_lock(&lock); 56 // printf("i'm pthread_c!\n"); 57 58 pthread_cond_wait(&cond,&lock); 59 printf("pthread_c buf:%s\n",buf); 60 if(strncmp(buf,"quit",4) == 0) 61 { 62 exit(0); 63 } 64 65 pthread_mutex_unlock(&lock); 66 } 67 pthread_exit(NULL); 68 } 69 70 int main(int argc, const char *argv[]) 71 { 72 //建立锁 73 pthread_mutex_init(&lock,NULL); 74 75 //建立条件变量 76 pthread_cond_init(&cond,NULL); 77 78 //线程调用 79 pthread_create(&tid1,NULL,fun_a,NULL); 80 pthread_create(&tid2,NULL,fun_b,NULL); 81 pthread_create(&tid3,NULL,fun_c,NULL); 82 83 //线程阻塞 84 pthread_join(tid1,NULL); 85 pthread_join(tid2,NULL); 86 pthread_join(tid3,NULL); 87 88 //回收锁 89 pthread_mutex_destroy(&lock); 90 91 //回收条件变量 92 pthread_cond_destroy(&cond); 93 94 return 0; 95 }