C语言线程基础(TinyCThread)

C语言线程基础(TinyCThread)

线程程是操作系统中进行运算调度的最小单位,它解决了同一个进程同一时刻只能占用一个核的问题,解决了同一个进程只能串行执行程序的问题

线程是程序的载体。

在这里插入图片描述

由于 msvc 并没有完整的线程包,所以需要去相关网站下载线程开源的库: http://tinycthread.github.io/ 。

使用 thrd_create() 函数创建新线程。thrd_create() 函数接收三个参数,一是新定义的线程地址,二是函数指针,三是函数指针对应的函数的参数。整体意义为开辟一个新线程,运行传入的函数指针指向的函数

#include <io_utils.h>
#include <tinycthread.h>
#include <stdio.h>

int SayHello(char *name){

  printf("This is a new thread, location: [%#x], content: [%s]\n", thrd_current(), name);

  return 0;
}

void main(void){
  thrd_t new_thread;
  int result = thrd_create(&new_thread, SayHello, "Hello World!");

  if(result == thrd_success){
    printf("Run in main thread: [%#x], create a new thread: [%#x]\n", thrd_current(), new_thread);
  }else{
    printf("Run in main thread: [%#x], failed to create a new thread\n", thrd_current());
  }
}

msvc 和 mingw 编译器的运行结果如下图所示。可以发现,新开的线程并没有运行。原因是主线程运行完毕后直接关闭,子线程还未运行

解决方法是利用 thrd_sleep() 函数使主线程 sleep 一段时间,等待子线程的运行。代码如下,thrd_sleep() 函数接收两个参数,一是 struct timespect 类型的时间,意为主线程应该等待的时间;二同样是struct timespect 类型的时间,意味着主线程实际等待的时间(实际等待时间小于应该等待时间)。

thrd_sleep(&(struct timespec){
    
    .tv_sec = 0, .tv_nsec = 1000000}, NULL);

使用 thrd_sleep() 函数可能会带来一些问题,例如子线程运行结束,但主线程还在 sleep。可以利用 thrd_join() 函数解决子线程和主线程问题。thrd_join() 函数可以通过阻塞将子线程与主线程连接起来,当子线程执行结束时,会继续运行主线程。thrd_join() 函数接收两个参数,一是给定的子线程,二是给定子线程执行结果的返回值。

#include <io_utils.h>
#include <tinycthread.h>

int SayHello(char *name) {
    
    
  PRINTLNF("Run in new thread[%#x]: Hello, %s", thrd_current(), name);
  return 1;
}

int main(void) {
    
    
  thrd_t new_thread;
  int result = thrd_create(&new_thread, SayHello, "C lang");
  if (result == thrd_success) {
    
    
    PRINTLNF("Run in Main thread[%#x], created new_thread[%#x]", thrd_current(), new_thread);
  } else {
    
    
    PRINTLNF("Run in Main Thread[%#x], failed to create new_thread", thrd_current());
  }
  thrd_sleep(&(struct timespec) {
    
    .tv_sec = 0, .tv_nsec = 100000000}, NULL);

  int res;
  thrd_join(new_thread, &res);
  PRINTLNF("Run in Main Thread[%#x], result from thread[%#x]: %d", thrd_current(), new_thread, res);
}

在这里插入图片描述

可以看出创建的子线程地址主线程地址相同。这种情况与 Windows 内部实现有关,此处利用 thrd_current() 函数获取的线程地址并非对应真正的线程 id。

thrd_yield() 函数:当前线程作出声明,主动让出 CPU 资源。不过具体的情况需要 CPU 做决定,这个函数仅仅是作出声明,资源可能并没有让出

线程在运行结束后不会主动释放资源,除非调用 thrd_join() 或 thrd_detach() 函数,线程资源才能够释放。thrd_detach() 函数类似于 fclose() 函数,传入待关闭的线程即可(thrd_detach(new_thread);)。注意, thrd_join() 或 thrd_detach() 函数两者均会关闭线程资源,是互斥关系,只能使用其一。

猜你喜欢

转载自blog.csdn.net/qq_23172985/article/details/129378831