C 语言的并发原语(一)
哈喽哈喽,我又来啦~
最近查资料发现C11标准C语言的标准库居然更新了,新增了C语言自己的并发原语,要知道在这之前的C语言想要并发要么依赖第三方库,要么依赖操作系统自己封装的库多么痛苦😭
现在C11标准往后都可以用C语言自身的并发原语啦~
这次帖子就先介绍C语言标准库中线程的用法
创建线程所使用的是thrd_create
函数它的函数签名为int thrd_create(thrd_t *__thr, thrd_start_t __func, void *__arg);
int
是它的返回值,线程创建成功返回thrd_success
创建失败返回thrd_error
thrd_t* __thr
是传入一个thrd_t
类型的指针,用于记录所创建的线程的id
thrd_start_t __func
是(int)(*)(void*)函数指针的类型别名,用于线程要执行的函数
void* __arg
线程要执行的函数的参数
等待线程线程结束使用的是thrd_join
函数,它的函数签名是int thrd_join (thrd_t __thr, int *__res);
int
是它的返回值,用于检查thrd_join
函数是否执行成功,执行成功返回值thrd_success
执行失败则返回值thrd_error
thrd_t __thr
需要传入需要阻塞的线程id
int* __res
是获取所阻塞的线程的返回值
#include <stdio.h>
#include <threads.h>
int
thrd_test(void* arg)
{
printf("%s\n", (char*)arg);
return 123;
}
int
main(int argc, char* argv[])
{
thrd_t n, m;
thrd_create(&n, thrd_test, "hello");
thrd_create(&m, thrd_test, "world");
printf("main\n");
int nres;
int mres;
thrd_join(n, &nres);
thrd_join(m, &mres);
printf("nres %d\n", nres);
printf("mres %d\n", mres);
}
thrd_join
的作用不只是等待指定线程结束,它承担着释放指定线程所占资源的任务,如果一个线程已经分离或者和已经join过的线程则会发生未定义的行为。创建线程后不进行join是一个危险的行为,当前程序的进程会因有线程没有释放错误的认为线程还在占用,进程将不会被系统回收资源将会产生僵尸线程或僵尸进程。
thrd_create
使用的函数是thrd_start_t
也就是int(*)(void*)
,这样的函数指针类型想要做到多参数还有多返回值会有一些麻烦,但是也不是不能做到
#include <stdio.h>
#include <threads.h>
int
thrd_test(void* arg)
{
void** a = arg;
char* hello = *a;
*(int*)a[1] = 123;
printf("%s\n", hello);
return 0;
}
int
main(int argc, char* argv[])
{
thrd_t n;
int num;
void* arg[] = { "hello", &num };
thrd_create(&n, thrd_test, arg);
thrd_join(n, NULL);
printf("%d\n", num); // 123
}
通过传入一个指针数组将自己想要传入的参数一起传入,这样就能做到多参数,并且再使用指针来接收函数中想要向外部传递的返回值(这在c语言中非常常见)。虽然有些麻烦但是它能很稳定的执行~毕竟写C语言在大部分时间里都是在做重复劳动
C语言中的返回值通常都是用来返回错误信息,所以一般都采取在函数的形参上标注哪个形参是用来接收返回值的,比如
thrd_join
形参中的int* __res
好了目前就介绍到这里,C11中剩下的线程相关的函数都比较简单且明了就不过多的介绍啦,以下是线程相关的信息感兴趣的小伙伴可以自己动手试一下~
- thrd_t 类型 线程唯一id的类型,是一个无符号长整型
- thrd_create 函数 创建一个线程
- thrd_join 函数 阻塞到指定线程结束为止
- thrd_equal 函数 检查两个线程id是否为同一个线程
- thrd_exit 函数 终止所在线程
- thrd_yield 函数 所在的线程让出当前时间切片
- thrd_sleep 函数 所在的线程让出当前时间切片,在指定时间后唤醒
- thrd_current 函数 获取所在线程的id
- thrd_detach 函数 分离指定线程,当指定线程结束后自动释放线程本身所占用的资源
- thrd_success 枚举状态 表示线程成功执行的返回值
- thrd_timeout 枚举状态 表示线程执行某个任务超时的返回值
- thrd_busy 枚举状态 表示当前线程因资源暂时不可用所以执行失败的返回值
- thrd_nomem 枚举状态 表示线程内存不足的返回值
- thrd_error 枚举状态 表示线程错误的返回值
- thrd_start_t 类型 是(int)(*)(void*)函数指针的类型别名,用于线程要执行的函数
看不懂
好
高级