1、进程与线程 进程是资源分配的最小单位,线程是程序执行的最小单位,在面向线程设计的系统中,进程本身不是基本运行单位,而是线程的容器。父进程通过fork一个子进程,是将相关代码进行拷贝,会消耗内存空间,线程是一个进程中不同的执行路径,有自己的堆栈,局部变量,没有独立的地址空间。一个线程死掉就等于整个进程死掉,所以多进程的程序要比多线程的程序健壮,但进程切换时,消耗资源大,效率低。对于一些要求同时进行并且又要共享某些变量的并发操作,只能用线程不能用进程。 2、线程开发API概要 多线程开发在 Linux 平台上已经有成熟的 pthread 库支持,在编译的过程中要加 -lpthread。其涉及的多线程开发的最基本概念主要包含三点:线程,互斥锁,条件。其中,线程操作又分线程的创建,退出,等待 3 种。互斥锁则包括 4 种操作,分别是创建,销毁,加锁和解锁。条件操作有 5 种操作:创建,销毁,触发,广播和等待。
函数原型
#include <pthread.h> //线程创建 int pthread_create(pthread_t *thread, const pthread_attr_t *attr, void *(*start_routine) (void *), void *arg); 参数一:线程id 参数二:线程属性,默认可置为NULL,表示线程属性取缺省值 参数三:线程入口函数 参数四:*线程入口函数的参数 //线程退出 void pthread_exit(void *retval); 参数:线程退出时的返回值,也可为NULL //线程等待 int pthread_join(pthread_t thread, void **retval); 参数二:收回线程的退出状态线程的返回值不感兴趣,可以把rval_ptr置为NULL //获取线程ID pthread_t pthread_self(void);demo实例
#include <stdio.h> #include <pthread.h> void *func(void *arg) { static char *p = "xiaobian henshuai"; printf("this is t1 thread pid=%ld\n",(unsigned long)pthread_self()); printf("deliver param is %d\n",*(int *)arg); pthread_exit((void *)p); //退出时返回退出时的状态,返回一个字符串 } int main() { pthread_t t1; char *p =NULL; int param = 10; pthread_create(&t1,NULL,func,(void*)¶m); //创建线程时,传递了一个param参数 pthread_join(t1,(void **)&p); //等待t1线程的退出,用p收集,t1线程退出时的状态 printf("return value is %s\n",p); return 0; } 执行结果 this is t1 thread pid=140537713628928 deliver param is 10 return value is xiaobian henshuai函数原型
#include <pthread.h> //互斥锁的初始化 int pthread_mutex_init(pthread_mutex_t *restrict mutex, const pthread_mutexattr_t *restrict attr); 参数一:互斥锁变量mutex 参数二:通常为NULL,为默认参数 //销毁互斥锁 int pthread_mutex_destroy(pthread_mutex_t *mutex); //加锁 int pthread_mutex_lock(pthread_mutex_t *mutex); //解锁 int pthread_mutex_unlock(pthread_mutex_t *mutex);demo实例
#include <stdio.h> #include <pthread.h> int data = 0;//定义一个全局变量验证线程是共享内存空间的 pthread_mutex_t mutex; void *func1(void *arg) { static char *p = "xiaobian henshuai"; printf("t1:this is t1 thread pid=%ld\n",(unsigned long)pthread_self()); printf("t1:deliver param is %d\n",*(int *)arg); int i=3; pthread_mutex_lock(&mutex);//加锁的目的是在执行以下代码的过程中不会被其他的进程打断 while(i--) { printf("t1:data=%d\n",data++); sleep(1); } pthread_mutex_unlock(&mutex); pthread_exit((void *)p); } void *func2(void *arg) { pthread_mutex_lock(&mutex); static char *p = "xiaobian henshuai"; printf("t2:this is t2 thread pid=%ld\n",(unsigned long)pthread_self()); printf("t2:deliver param is %d\n",*(int *)arg); while(1) { printf("t2:data=%d\n",data++); sleep(1); } pthread_mutex_unlock(&mutex); pthread_exit((void *)p); } int main() { pthread_t t1; pthread_t t2; char *p =NULL; int param = 10; pthread_create(&t1,NULL,func1,(void*)¶m); pthread_create(&t2,NULL,func2,(void*)¶m); pthread_mutex_init(&mutex,NULL); pthread_join(t1,(void **)&p); pthread_join(t2,(void **)&p); pthread_mutex_destroy(&mutex); printf("main:return value is %s\n",p); return 0; } 执行结果 t1:this is t1 thread pid=139923829593856 t1:deliver param is 10 t1:data=0 t1:data=1 t1:data=2 t2:this is t2 thread pid=139923821201152 t2:deliver param is 10 t2:data=3 t2:data=4 t2:data=5 t2:data=6 t2:data=7 t2:data=8 ^C死锁是怎么产生的: 前提是有两个锁,线程一获得锁一的同时,又想获得锁二,线程二获得锁二的同时,又想获得锁一,线程一和二都想拿到对方的锁,导致线程停滞不前。
函数原型
#include <pthread.h> //创建条件变量 int pthread_cond_init(pthread_cond_t *restrict cond, const pthread_condattr_t *restrict attr); //销毁条件变量 int pthread_cond_destroy(pthread_cond_t* cond); //等待 int pthread_cond_wait(pthread_cond_t *restrict cond, pthread_mutex_t *restrict mutex); //触发 int pthread_cond_signal(pthread_cond_t c*ond) //广播 int pthread_cond_broadcast(pthread_cond_t cond);demo实例
#include <stdio.h> #include <pthread.h> #include <stdlib.h> int data = 0; pthread_mutex_t mutex; pthread_cond_t cond; void *func1(void *arg) { printf("t1:this is t1 thread pid=%ld\n",(unsigned long)pthread_self()); printf("t1:deliver param is %d\n",*(int *)arg); while(1) { pthread_cond_wait(&cond,&mutex);//等待某个条件的唤醒 printf("t1 run========\n"); data=0; } } void *func2(void *arg) { printf("t2:this is t2 thread pid=%ld\n",(unsigned long)pthread_self()); printf("t2:deliver param is %d\n",*(int *)arg); while(1) { printf("t2:data=%d\n",data); pthread_mutex_lock(&mutex); data++; if(data==3) { pthread_cond_signal(&cond);//唤醒条件执行线程t1 } pthread_mutex_unlock(&mutex); sleep(1); } } int main() { pthread_t t1; pthread_t t2; char *p =NULL; int param = 10; pthread_create(&t1,NULL,func1,(void*)¶m); pthread_create(&t2,NULL,func2,(void*)¶m); pthread_mutex_init(&mutex,NULL); pthread_cond_init(&cond,NULL); pthread_join(t1,(void **)&p); pthread_join(t2,(void **)&p); pthread_mutex_destroy(&mutex); pthread_cond_destroy(&cond); printf("main:return value is %s\n",p); return 0; 执行结果 t2:this is t2 thread pid=140397643106048 t2:deliver param is 10 t2:data=0 t1:this is t1 thread pid=140397651498752 t1:deliver param is 10 t2:data=1 t2:data=2 t1 run======== t2:data=0 t2:data=1 t2:data=2 t1 run======== t2:data=0 t2:data=1 t2:data=2 t1 run======== t2:data=0 ^C