多线程编程
更新: 3/3/2025 字数: 0 字 时长: 0 分钟
线程使用
获取线程号
//获取线程号
#include <pthread.h>
pthread_t pthread_self(void);
线程创建
//创建线程
#include <pthread.h>
int pthread_create(pthread_t *thread, const pthread_attr_t *attr,void *(*start_routine) (void *), void *arg);
该函数第一个参数为 pthread_t 指针,用来保存新建线程的线程号;
第二个参数表示了线程的属性,一般传入 NULL 表示默认属性;
第三个参数是一个函数指针,就是线程执行的函数。这个函数返回值为 void*,形参为void*;
第四个参数则表示为向线程处理函数传入的参数,若不传入,可用 NULL 填充,有关线程传参后续小节会有详细的说明,接下来通过一个简单例程来使用该函数创建出一个线程。
例程
#include <pthread.h>
#include <stdio.h>
#include <unistd.h>
#include <errno.h>
void *fun1(void *arg)
{
printf("%s:arg = %d Addr = %p\n",__FUNCTION__,*(int *)arg,arg);
}
void *fun2(void *arg)
{
printf("%s:arg = %d Addr = %p\n",__FUNCTION__,(int)(long)arg,arg);
}
int main()
{
pthread_t tid1,tid2;
int a = 50;
int ret = pthread_create(&tid1,NULL,fun1,(void *)&a);
if(ret != 0){
perror("pthread_create");
return -1;
}
ret = pthread_create(&tid2,NULL,fun2,(void *)(long)a);
if(ret != 0){
perror("pthread_create");
return -1;
}
sleep(1);
printf("%s:a = %d Add = %p \n",__FUNCTION__,a,&a);
return 0;
}
线程的退出与回收
1. 线程主动退出
//线程主动退出
#include <pthread.h>
void pthread_exit(void *retval);
pthread_exit 函数为线程退出函数,在退出时候可以传递一个 void*类型的数据带给主线程,若选择不传出数据,可将参数填充为 NULL。
2. 线程被动退出
//线程被动退出,其他线程使用该函数让另一个线程退出
#include <pthread.h>
int pthread_cancel(pthread_t thread);
//成功:返回 0
该函数传入一个 tid 号,会强制退出该 tid 所指向的线程,若成功执行会返回 0。
3. 线程资源回收(阻塞方式)
//线程资源回收(阻塞)
#include <pthread.h>
int pthread_join(pthread_t thread, void **retval);
该函数为线程回收函数,默认状态为阻塞状态,直到成功回收线程后才返回。第一个参数为要回收线程的 tid 号,第二个参数为线程回收后接受线程传出的数据。
4. 线程资源回收(非阻塞方式)
线程资源回收(非阻塞)
#define _GNU_SOURCE
#include <pthread.h>
int pthread_tryjoin_np(pthread_t thread, void **retval);
该函数为非阻塞模式回收函数,通过返回值判断是否回收掉线程,成功回收则返回 0,其余参数与 pthread_join 一致。
线程控制
互斥锁 API
1. 初始化互斥量
int pthread_mutex_init(phtread_mutex_t *mutex,const pthread_mutexattr_t *restrict attr);
该函数初始化一个互斥量,第一个参数是改互斥量指针,第二个参数为控制 互斥量的属性,一般为 NULL。当函数成功后会返回 0,代表初始化互斥量成功。
当然初始化互斥量也可以调用宏来快速初始化,代码如下:
pthread_mutex_t mutex = PTHREAD_MUTEX_INITALIZER;
2. 互斥量加锁/解锁
//互斥量加锁(阻塞) /解锁
#include <pthread.h>
int pthread_mutex_lock(pthread_mutex_t *mutex);
int pthread_mutex_unlock(pthread_mutex_t *mutex);
//成功:返回 0
lock
函数与unlock
函数分别为加锁解锁函数,只需要传入已经初始化好的pthread_mutex_t
互斥量指针。 成功后会返回 0。
当某一个线程获得了执行权后,执行lock
函数,一旦加锁成功后,其余线程遇到lock
函数时候会发生阻塞,直至获取资源的线程执行unlock
函数后。unlock
函数会唤醒其他正在等待互斥量的线程。
特别注意的是,当获取lock
之后,必须在逻辑处理结束后执行unlock
,否则会发生死锁现象!导致其余线程一 直处于阻塞状态,无法执行下去。在使用互斥量的时候,尤其要注意使用pthread_cancel
函数,防止发生死锁现象!
3. 互斥量加锁(非阻塞方式)
//互斥量加锁(非阻塞)
#include <pthread.h>
int pthread_mutex_trylock(pthread_mutex_t *mutex);
//互斥量销毁
#include <pthread.h>
int pthread_mutex_destory(pthread_mutex_t *mutex);
//成功:返回 0
例程
#define _GNU_SOURCE
#include <pthread.h>
#include <stdio.h>
#include <unistd.h>
#include <errno.h>
pthread_mutex_t mutex;
int Num = 0;
void *fun1(void *arg)
{
pthread_mutex_lock(&mutex);
while(Num < 3){
Num++;
printf("%s:Num = %d\n",__FUNCTION__,Num);
sleep(1);
}
pthread_mutex_unlock(&mutex);
pthread_exit(NULL);
}
void *fun2(void *arg)
{
pthread_mutex_lock(&mutex);
while(Num > -3){
Num--;
printf("%s:Num = %d\n",__FUNCTION__,Num);
sleep(1);
}
pthread_mutex_unlock(&mutex);
pthread_exit(NULL);
}
int main()
{
int ret;
pthread_t tid1,tid2;
ret = pthread_mutex_init(&mutex,NULL);
if(ret != 0){
perror("pthread_mutex_init");
return -1;
}
ret = pthread_create(&tid1,NULL,fun1,NULL);
if(ret != 0){
perror("pthread_create");
return -1;
}
ret = pthread_create(&tid2,NULL,fun2,NULL);
if(ret != 0){
perror("pthread_create");
return -1;
}
pthread_join(tid1,NULL);
pthread_join(tid2,NULL);
pthread_mutex_destroy(&mutex);
return 0;
}
信号量API
TODO