目录
1.线程相关
2.线程的相关函数
2.1 创建线程
2.2 等待线程
2.3 退出线程编辑
2.4 取消线程编辑
3.线程的同步和互斥(多线程间通信、同步、互斥)
3.1 多线程的数据通信-->使用全局变量
3.2 多线程的同步
函数库:存放一堆接口文件的函数,没有主函数
linux的两类函数库:动态库(.so),静态库(.a),
动态库和静态库的区别:
后缀不同,
使用时刻不同,编译(静态库),运行(动态库)
可移植性,静态库的可移植性好
系统调用函数:操作系统为应用程序提供的接口
库函数在操作系统之外
线程:多个任务结构体共享相同的地址空间,是一种轻量级的进程,没有自己独立的内存空间,共享创建它的进程的内存空间
好处:1.使用线程切换效率高
2.避免了额外的TLB和cache(高速缓存器)的刷新
*thread:指向线程ID的指针
*attr :指向线程属性的指针,通常给NULL
参数3:指向线程执行函数的函数指针
*arg :传给线程执行函数
返回值:成功返回0,失败返回错误
#include
#include
#include
void *ThreadFunc(void *arg)
{
printf("2022-12-01\r\n");
}
int main()
{
printf("hello---\r\n");
pthread_t tID=-1;
//int pthread_create(pthread_t *thread,const pthread_attr_t *attr,void*(*routine)(void *),void *arg)
//thread 指向线程的指针
//*attt 指向线程的属性的指针(通常NULL)
//routine 线程执行的函数
//arg 传递给线程执行函数的参数
if(0!=pthread_create(&tID,NULL,ThreadFunc,NULL))
{
printf("create error----\r\n");
return -1;
}
sleep(1);
printf("********************\r\n");
return 0;
}
作用:阻塞等待线程结束,并回收状态值
thread :要等待的线程ID
**value_ptr :指向线程退出状态值的指针
#include
#include
void *ThreadFunc1(void *arg)
{
printf("2022-12-01\r\n");
}
void *ThreadFunc2(void *arg)
{
printf("2022-12-02\r\n");
}
int main()
{
printf("hello---\r\n");
pthread_t tID1=-1;
pthread_t tID2=-1;
//创建两个线程
if(0!=pthread_create(&tID1,NULL,ThreadFunc1,NULL))
{
printf("create error----\r\n");
return -1;
}
if(0!=pthread_create(&tID2,NULL,ThreadFunc2,NULL))
{
printf("create error----\r\n");
return -1;
}
//pthread_join(pthread_t thread,void **value_ptr)
//thread 要等待的线程
//**value_ptr 指针*value_ptr指向线程返回的参数
pthread_join(tID1,NULL);
pthread_join(tID2,NULL);
printf("********************\r\n");
return 0;
}
作用:线程退出
#include
#include
#include
void *ThreadFunc(void *arg)
{
printf("2022-12-01\r\n");
pthread_exit(0);
printf("未退出\r\n");
}
int main()
{
printf("hello---\r\n");
pthread_t tID=-1;
//int pthread_exit(void *value_ptr)
//*value_ptr 线程退出时返回的值
//返回值:成功返回0
if(0!=pthread_create(&tID,NULL,ThreadFunc,NULL))
{
printf("create error----\r\n");
return -1;
}
sleep(1);
printf("********************\r\n");
return 0;
}
unubtu =linux内核+各种工具+桌面管理器+各种库(标准C库,第三方线程库)+各种应用程序
#include
#include
#include
//int pthread_cancel(pthread_t thread)
//thread 线程的ID
void *ThreadFunc(void *arg)
{
//1.
//pthread_t tID=-1;
//pthread_cancel(tID);
printf("2022-12-01\r\n");
}
int main()
{
printf("hello---\r\n");
pthread_t tID=-1;
if(0!=pthread_create(&tID,NULL,ThreadFunc,NULL))
{
printf("create error----\r\n");
return -1;
}
//pthread_cancel(pthread_t thread)
//thread 要取消的线程的ID
//2.
if(pthread_cancel(tID)==0)
{
printf("取消成功\r\n");
}
printf("********************\r\n");
return 0;
}
a.在一个进程中可以创建多个线程,那么多个线程间会存在数据通信问题,会存在两个线程相互配合完成一个事件,就构成了线程的同步问题,会存在两个线程对公共资源的竞态访问问题
./pthread_com1 hhh
同步:按照一定的顺序完成某个问题,两个进程或两个线程按照一定的顺序相互配合完成一件事情
第一个进程(线程)和第二个进程(线程)之间有通信
案例:在线程1中1s中打印一个hello,在线程2中1s打印一个world,交替打印,各打印10次
(1)无P/V操作
缺点:顺序会乱
(2)有P/V操作
无名信号量:sem_t;
P/V操作函数控制sema和semb
P操作:sem_wait(&sema) 含义:sem_wait会检测信号量sema的值是否大于0,若大于0,将sema的值减1,同时返回;若等于0,阻塞当前线程
V操作:sem_post(&semb) 含义:sem_post只会给检测的信号量semb的值加1,非阻塞函数
互斥的引入:多个线程可能会使用同一段公共资源,若是同时访问这段公共资源,那么就会造成多个线程对公共资源的竞争,从而造成访问结果混乱。
解决方法:使用互斥锁
1.多个线程能否使用同一个线程执行函数(可以)
2.两个线程给线程执行函数传入不同的参数,最后结果是否发生混乱
3.使用互斥锁解决两线程互斥访问公共资源
pthread_mutex_t mutex;//线程互斥锁
pthread_mutex_init(&mutex,NULL); //线程互斥锁的调用
&mutex:指向互斥锁