线程
程序运行后是进程,而线程寄生于进程之上,可以让一个进程中同时干不止一件事。进程有独立的地址空间,一个进程崩溃后,不会影响其他进程,而线程是寄托于进程之上一个进程死亡则整个线程死亡。
线程特性
1. 节省空间,提升效率(人多干活快)
2. 方便通信(多个线程寄生于同一个进程,线程A变换数据,线程B可以立即知道)
线程相关API
pthread_create创建进程
- 原型
#include <pthread.h>
int pthread_create(pthread_t *restrict tidp, const pthread_attr_t *restrict attr, void *(*start_rtn)(void *), void *restrict arg);
- pthread_t *restrict tidp —— 线程名
- const pthread_attr_t *restrict attr —— 线程属性(NULL为默认)
- void *(*start_rtn)(void *) —— 需要线程运行的代码
- void *restrict arg —— 运行代码需要传入的参量(如有多个参数则放入到一个结构体中)
- 示例
创建一个进程打印一句话
#include<stdio.h>
#include<pthread.h>
void *func1(void *arg)
{
printf("this is func1 print\n");
}
int main()
{
pthread_t t1;
ret = pthread_create(&t1,NULL,func1,(void *)¶m);
return 0;
}
pthread_join线程等待
- 原型
#include <pthread.h>
int pthread_join(pthread_t thread, void **rval_ptr);
- pthread_t thread —— 线程名
- void **rval_ptr —— 线程的返回值(不感兴趣设为NULL)
- 示例
等待线程结束后主进程才会结束,否则阻塞进程结束
#include<stdio.h>
#include<pthread.h>
void *func1(void *arg)
{
printf("t1 %ld thread is create\n",(unsigned long)pthread_self()); //打印线程ID
printf("t1 param is %d\n",*((int *)arg)); //打印传来的param值
}
int main()
{
int ret;
int param = 100;
pthread_t t1;
ret = pthread_create(&t1,NULL,func1,(void *)¶m);
if(ret == 0){ //判断是否创建成功
printf("creat t1 success\n");
}
printf("main %ld \n",(unsigned long)pthread_self());
pthread_join(t1,NULL); //等待线程结束
return 0;
}
pthread_exit线程退出
- 原型
#include <pthread.h>
int pthread_exit(void *rval_ptr);
- void *rval_ptr —— 线程退出后返回给等待函数的值
- 示例
线程退出后将值传递回等待函数
#include<stdio.h>
#include<pthread.h>
void *func1(void *arg)
{
static int ret = 10; //必须为static类型否则传地址混乱
pthread_exit((void *)&ret);
}
int main()
{
int ret;
int param = 100;
pthread_t t1;
int *pret = NULL;
ret = pthread_create(&t1,NULL,func1,(void *)¶m); //创建进程
pthread_join(t1,(void **)&pret); //(void **)为pthread_join的格式
printf("main: t1 quit:%d\n",*pret);
return 0;
}
锁
在多个线程同时运行时,无法保证线程A运行时线程B等待其运行结束后再运行,锁就发挥作用。
当线程A运行时可以上锁导致其他线程无法运行,只有线程A开锁后其他线程才可以开始抢夺运行权。
锁相关API
pthread_mutex_t mutex创锁
pthread_mutex_destroy消锁
- 原型
#include <pthread.h>
int pthread_mutex_init(pthread_mutex_t *restrict mutex, const pthread_mutexattr_t *restrict attr);
int pthread_mutex_destroy(pthread_mutex_t mutex);
- pthread_mutex_t *restrict mutex —— 锁名
- const pthread_mutexattr_t *restrict attr —— 默认量NULL即可
- 示例
建立锁并且消锁
pthread_mutex_t mutex;
pthread_mutex_init(&mutex,NULL); //创锁
pthread_mutex_destroy(&mutex); //消锁
pthread_mutex_lock上锁
pthread_mutex_unlock解锁
- 原型
#include <pthread.h>
int pthread_mutex_lock(pthread_mutex_t mutex);
int pthread_mutex_unlock(pthread_mutex_t mutex);
- pthread_mutex_t mutex —— 锁名
- 示例
一旦有一线程抢先上锁后另外一线程将无法运行
#include<stdio.h>
#include<pthread.h>
#include <unistd.h>
pthread_mutex_t mutex; //定义锁名
void *func1(void *arg)
{
int i;
pthread_mutex_lock(&mutex); //上锁
for(i=0;i<5;i++){
printf("t1 param is %d\n",*((int *)arg));
}
pthread_mutex_unlock(&mutex); //解锁
}
void *func2(void *arg)
{
pthread_mutex_lock(&mutex); //上锁
printf("t2 param is %d\n",*((int *)arg));
pthread_mutex_unlock(&mutex); //解锁
}
int main()
{
int ret;
int param = 100;
pthread_t t1;
pthread_t t2;
char *pret = NULL;
pthread_mutex_init(&mutex,NULL); //建锁
ret = pthread_create(&t1,NULL,func1,(void *)¶m); //建立线程1
ret = pthread_create(&t2,NULL,func2,(void *)¶m); //建立线程2
pthread_join(t1,(void **)&pret); //等待线程1结束
pthread_join(t2,(void **)&pret); //等待线程2结束
pthread_mutex_destroy(&mutex); //消锁
return 0;
}
条件变量
使用锁后依旧无法控制线程的顺序问题,使用条件变量后可以调节其先后问题。
条件变量相关API
pthread_cond_init创建条件变量
pthread_cond_destroy删除条件变量
- 原型
#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);
- pthread_cond_t *restrict cond —— 条件变量名
- const pthread_condattr_t *restrict attr —— 默认量NULL即可
- 示例
pthread_cond_t cond;
pthread_cond_init(&cond,NULL);
pthread_cond_destroy(&cond);
pthread_cond_wait等待
pthread_cond_signal触发
- 原型
#include <pthread.h>
int pthread_cond_wait(pthread_cond_t *restrict cond, pthread_mutex_t *restrict mutex);
- pthread_cond_t *restrict cond —— 条件变量名
- pthread_mutex_t *restrict mutex —— 锁名
#include <pthread.h>
int pthread_cond_signal(pthread_cond_t cond);
- pthread_cond_t cond —— 条件变量名地址
- 示例
进程2先运行当g_data加到3时触发信号,进程1运行并将g_data归零
#include<stdio.h>
#include<pthread.h>
#include <unistd.h>
int g_data = 0;
pthread_mutex_t mutex; //定义锁名
pthread_cond_t cond; //定义条件变量名
void *func1(void *arg)
{
while(1){
pthread_cond_wait(&cond,&mutex); //等待触发
printf("t1 run\n");
printf("t1:%d\n",g_data);
g_data = 0;
sleep(1);
}
}
void *func2(void *arg)
{
while(1){
printf("t2:%d\n",g_data);
pthread_mutex_lock(&mutex); //上锁
g_data++;
if(g_data == 3){
pthread_cond_signal(&cond); //触发条件变量
}
pthread_mutex_unlock(&mutex); //解锁
sleep(1);
}
}
int main()
{
int ret;
int param = 100;
pthread_t t1;
pthread_t t2;
char *pret = NULL;
pthread_mutex_init(&mutex,NULL); //创建锁
pthread_cond_init(&cond,NULL); //创建条件变量
ret = pthread_create(&t1,NULL,func1,(void *)¶m); //建成进程1
ret = pthread_create(&t2,NULL,func2,(void *)¶m); //建成进程2
pthread_join(t1,(void **)&pret); //等待进程1
pthread_join(t2,(void **)&pret); //等待进程2
pthread_mutex_destroy(&mutex); //消锁
pthread_cond_destroy(&cond); //删除条件变量
return 0;
}