2019年12月6日更新
首先要感谢评论区的热心的同学们的提醒,经本人亲自验证:
VS 2019中移除了对threads.h的支持(评论区有同学提到单独安装v140工具集可以实现支持,但是测试发现没有效果),而GCC方面则在最新版中加入了对该头文件的支持。
以下为原文(程序代码部分更新了Linux版Dome)。
导语
threads.h
是C11标准新增的多线程支持库,在此之前C语言实现多线程,除了使用系统API外用的最多的就是pthread.h
了,threads.h
在语法上和pthread.h
非常相似。
当然,对于新出的C语言标准,各大编译器厂商并不会马上就支持。就比如说,Linux下主流的C语言编译器————GCC,直到GCC7.2版本都没能支持该库(PS:看到老外网站上说要安装最新版glibc
才能获得对该库的支持,然而亲测无卵用)。相反,VS在这方面做的就很不错,VS2017已经可以完美支持该库了,本文也将基于VS2017社区版对该库的使用方法做介绍。
注:本文仅对多线程编程的概念及
threads.h
库文件的使用方法做简单介绍,并不会详尽介绍该库下的所有函数,如果你需要一个函数功能的参考手册可以参考此篇文章:C11新增多线程支持库-threads.h参考手册
以一个小程序为例子
本程序中使用到的库函数及宏:
- thrd_t //此宏定义用于存放线程标识符的数据类型
- thrd_create //此函数用于创建线程
- thrd_detach //此函数用于通知操作系统,当线程结束时由操作系统负责释放资源
- thrd_exit //此函数用于结束当前线程
程序功能:
主线程每2秒打印一次“I love ibadboy.net~~~”,共打印10次。子线程每1秒打印一次“He love ibadboy.net!!!”,共打印10次。我们知道,在只有一个主线程的C程序中该功能是无法实现的,因为后一段程序代码必须等待前一段代码执行完毕才可执行。但,在多线程编程中,各个线程可以一起执行(这里涉及到的同步、异步等等的高阶技术就不讨论了)。举个例子:在游戏开发中,如果程序需要实时监控用户键盘的输入,就不能把这段代码放到主线程中,因为这样的话该段代码就会被程序的其他部分阻塞掉而无法做到真正的“实时”,这时就可以利用多线程技术来化解尴尬啦!话不多说,直接上代码!
程序代码Linux版本
#include <stdio.h> #include <unistd.h> //包含sleep等函数 #include <stdbool.h> #include <threads.h> //包含多线程支持库头文件 #include <stdlib.h> //包含exit等函数 int thr_fun(void *); int main(void) { thrd_t thr; int ret; //保存thrd_create函数的返回值用于判断线程是否创建成功:0为成功,1为失败。 ret = thrd_create(&thr, thr_fun, NULL); //将thr_fun函数放在一个新的线程中执行 if (ret != thrd_success) { printf("error!!!\n"); getchar(); exit(-1); } ret = thrd_detach(thr); //通知操作系统,该线程结束时由操作系统负责释放资源。 if (ret != thrd_success) { printf("error!!!\n"); getchar(); exit(-1); } for (int i = 0; i < 10; i++) { sleep(2); printf("I love ibadboy.net~~~\n"); } getchar(); return 0; } int thr_fun(void *argv) { int i = 0; while (true) { i++; sleep(1); printf("He love ibadboy.net!!!\n"); if (i == 10) { thrd_exit(0); } } }
编译命令:
gcc a.c -std=c11 -lpthread
程序代码Windows版本(经测试在VS 2019中已无法编译通过):
#include<stdio.h> #include<stdbool.h> #include<thr/threads.h> //包含多线程支持库头文件 #include<Windows.h> void thr_fun(void); int main(void) { thrd_t thr; int ret; //保存thrd_create函数的返回值用于判断线程是否创建成功:0为成功,1为失败。 ret = thrd_create(&thr, thr_fun, NULL); //将thr_fun函数放在一个新的线程中执行 if (ret != thrd_success) { printf("error!!!\n"); getchar(); exit(-1); } ret = thrd_detach(thr); //通知操作系统,该线程结束时由操作系统负责释放资源。 if (ret != thrd_success) { printf("error!!!\n"); getchar(); exit(-1); } for (int i = 0; i < 10; i++) { Sleep(2000); printf("I love ibadboy.net~~~\n"); } getchar(); return 0; } void thr_fun(void) { int i = 0; while (true) { i++; Sleep(1000); printf("He love ibadboy.net!!!\n"); if (i == 10) { thrd_exit(0); } } }
程序输出:
程序中用到的库函数介绍:
thrd_create
函数用于创建新线程,如果创建成功,该函数会返回thrd_success
,否则返回thrd_error
。
函数原型:
int thrd_create(thrd_t *thr, thrd_start_t func, void *arg);
参数说明:
- thr:指向放置新线程标识符的内存位置的指针。
- func:要放在子线程中执行的函数。
- arg:传递给执行的函数的参数,无参数填NULL。
thrd_detach
函数用于通知操作系统,当线程结束后由操作系统负责释放资源,如果成功,则返回thrd_success
,否则为thrd_error
,如不调用该函数,则线程所使用的资源将在程序全部执行完后才会释放。
函数原型:
int thrd_detach( thrd_t thr );
参数说明:
- thr:要作用的线程的标识符
thrd_exit
函数用于结束当前进程,值得一提的是:使用该函数可以在不影响子进程的情况下结束主进程,而使用exit
函数的话结束主进程将会连带结束整个程序。
函数原型:
_Noreturn void thrd_exit( int res );
参数说明:
- res:要返回的值
结语
看完此篇文章相信你已经对使用threads.h
库进行C语言的多线程开发有了初步了解,如果还有什么问题的话欢迎在评论区留言哦~
Leave a Reply