C语言创建线程thread_create()的方法

在头文件 threads.h 中,定义和声明了支持多线程的宏、类型和函数。所有直接与线程相关的标识符,均以前缀 thrd_ 作为开头。例如,thrd_t 是一个对象类型,它标识了一个线程。

函数 thrd_create()用于创建并开始执行一个新线程。函数 thrd_create()的其中一个参数为在新线程中需要被执行的函数 thrd_create()的其中一个参数为在新线程中需要被执行的函数。thrd_create()的完整原型是:

int thrd_create(thrd_t *thr, thrd_start_t func, void *arg);

参数 func 是一个指针,它指向在新线程需要被执行的函数,而 void 指针 arg 用于向该函数传递参数。换句话说,新线程将执行函数调用 func(arg)。

参数 func 的类型为 thrd_start_t,它被定义为 int(*)(void*)(这是一个函数指针,指向一个 void 指针作为其参数并返回一个 int 值的函数),因此,该线程执行的函数返回一个 int 类型的值。

程序在后续过程中可以通过调用函数 thread_join()获得这个 int 类型的返回值(必要时,需等待该线程执行完)。

如果一个线程启动成功,函数 thread_create()将新线程写入一个对象进行标识,并通过参数 thr 指向该对象,然后返回宏值 thread_success。

在大多数情况下,后续的其他操作均依赖于该线程的执行结果,并且只有当该线程完成后,才能执行其他操作。函数 thread_join()用于确保一个线程已完成。它的原型是:

int thrd_join(thrd_t thr, int *result);

调用 thread_join()的线程会被阻塞,直到通过 thr 标识的线程执行完成,这里“阻塞”(block)指的是:线程会在调用 thread_join()的位置停留必要的时间。然后,thread_join()将线程 thr 中执行函数的返回值写入指针 result 所引用的 int 变量中,假设 result 不是一个空指针。最后,thread_join()释放属于线程 thr 的所有资源。

如果程序逻辑上并不需要等待线程 thr 结束,则应该调用以下函数:

int thrd_detach(thrd_t thr);

thrd_detach()使得当线程 thr 执行完成后,自动释放线程占用的所有资源。一旦一个线程执行了分离操作(调用 thrd_detach()),将不用程序等待其结束,程序也不会获得该线程执行函数的返回值。对于每个创建的线程,调用 thread_join()或 thread_detach()不得超过一次。

在例 1 中的程序展示了使用并行操作处理数组的一种方式。各个线程先自行处理数组的各部分,然后将它们的处理结果组合在一起。该程序仅需计算一个数字序列的总和。

函数 sum()首先根据创建线程的最大数量确定划分数组所得的各组元素的最大数量,然后调用递归辅助函数 parallel_sum()。

函数 parallel_sum()将数组平均分为两半,将其中的一半交给一个新线程处理,同时调用自身来处理另一半数组。如该例所示,一个线程函数需要多个参数,这些参数通常采用结构进行封装。

【例1】在几个并行线程中计算数组元素的和

#include <stdbool.h>
#include <threads.h>
#define MAX_THREADS 8      // 1、2、4、8……所创建线程数量的最大值
#define MIN_BLOCK_SIZE 100   // 一个数组块的最小值
typedef struct         // 函数parallel_sum()的参数
{
  float *start;    // 传递给parallel_sum()的数组块的起始地址
  int len;      // 数组块长度
  int block_size;   // 最小数组块的大小
  double sum;         // 求和结果
} Sum_arg;
int parallel_sum(void *arg);  // 线程函数的原型
// ---------------------------------------------------------------
// 计算数组元素的和,并写入*sumPtr
// sum()调用函数parallel_sum()进行并行处理
// 返回值:如果没有发生错误,则返回true;否则,返回false
bool sum(float arr[], int len, double* sumPtr)
{
  int block_size = len / MAX_THREADS;
  if (block_size < MIN_BLOCK_SIZE) block_size = len;
  Sum_arg args = { arr, len, block_size, 0.0 };
  if (parallel_sum(&args))
  { *sumPtr = args.sum; return true; }
  else
    return false;
}
// ---------------------------------------------------------------
// 递归辅助函数,用以将工作分解到几个线程中处理
int parallel_sum(void *arg)
{
  Sum_arg *argp = (Sum_arg*)arg;       // 指向参数的指针
  if (argp->len <= argp->block_size)         // 如果length <= block_size,
                            // 对所有元素求和
  {
    for (int i = 0; i < argp->len; ++i)
      argp->sum += argp->start[i];
    return 1;
  }
  else                        // 如果length > block_size,
                            // 分解数组
  {
    int mid = argp->len / 2;
    Sum_arg arg2 = { argp->start+mid, argp->len-mid,
             argp->block_size, 0};    // 指定后一半数组
    argp->len = mid;           // 前一半数组的长度
    thrd_t th;               // 在新线程中处理前一半数组
    int res = 0;
    if (thrd_create(&th, parallel_sum, arg) != thrd_success)
      return 0;              // 没能成功创建新线程
    if (!parallel_sum(&arg2))  // 在当前线程下,以递归方式处理后一半数组
    {
      thrd_detach(th); return 0;     // 递归调用失败
    }
    thrd_join(th, &res);
    if (!res)
      return 0;      // 同级线程报告执行失败
    argp->sum += arg2.sum;
    return 1;
  }
}

到此这篇关于C语言创建线程thread_create()的方法的文章就介绍到这了,更多相关C语言创建线程 内容请搜索我们以前的文章或继续浏览下面的相关文章希望大家以后多多支持我们!

(0)

相关推荐

  • C语言实现支持动态拓展和销毁的线程池

    本文实例介绍了C 语言实现线程池,支持动态拓展和销毁,分享给大家供大家参考,具体内容如下 实现功能 1.初始化指定个数的线程 2.使用链表来管理任务队列 3.支持拓展动态线程 4.如果闲置线程过多,动态销毁部分线程 #include <stdio.h> #include <pthread.h> #include <stdlib.h> #include <signal.h> /*线程的任务队列由,函数和参数组成,任务由链表来进行管理*/ typedef str

  • c语言实现多线程动画程序示例

    该程序是利用opengl图形库与fmod音频库写的一个简单3d动画程序.该程序在vs下运行良好,若缺少相关dll文件请确认已配制fmod与opengl库. mixmodel.cpp 复制代码 代码如下: // mixmodel.cpp : 定义控制台应用程序的入口点.// #include "stdafx.h" //定义一个线程DWORD WINAPI SoundProc( LPVOID LPVIDEOPARAMETERS);//光照变量GLfloat  whiteLight[] =

  • C语言实现多线程定时器实例讲解

    1. 大致功能介绍 实现任务列表,定时器会间隔一段时间遍历列表发现要执行的任务 任务列表中的所有任务并行执行 每个任务都可以有自己的定时器,并且可以选择是否要重复执行 定义方便的任务函数实现接口 定时器可以由用户自定义何时启动和停止 提供等待功能,保证任务列表中的所有任务执行完成 提供任务列表的传参功能 2. API库介绍 void setTick(int val); 设置定时间的间隔时间tick,若设置tick为1000,且任务的定时器时间为1000,则任务会在1秒后执行,默认tick为1秒,

  • c语言线程终止练习示例

    复制代码 代码如下: #include <stdio.h>#include <stdlib.h>#include <pthread.h> void *t1(void *args) { return (void *) 0;} void *t2(void *args) { printf("thread 2 param[args] = %d\n", args); pthread_exit((void *) 3);} void *t3(void *args)

  • c语言多线程编程使用示例

    复制代码 代码如下: #include <stdio.h>#include <stdlib.h>#include <pthread.h> #define THREAD_NUM 10 void *test(void *args) { printf("tid %d: i say 'Hello'.\n", args); return NULL;} int main() { int i, err; pthread_t child[THREAD_NUM]; f

  • c语言socket多线程编程限制客户端连接数

    先上一些多线程需要使用的函数定义: 复制代码 代码如下: DWORD WINAPI ProcessClientRequests(LPVOID lpParam)  //新线程将会执行的函数定义{      return 0;} HANDLE handler=CreateThread(NULL, 0, ProcessClientRequests, &clientsocket, 0, NULL);   //这里比较简单,&clientsocket是个指针,是从主线程传入新线程的参数 WaitFo

  • C语言实现用户态线程库案例

    轮子年年有人造,我们也来凑热闹,参考协程实现,大概有以下几种方法: 1)利用setjmp,longjmp 2)利用ucontext接口函数 3)汇编 (线程无非就是多了个抢占功能,由定时器触发,而非自愿让出运行权限) 因为我写的时候还没看到其他帖子,如果看到了,铁定会用最直观的ucontext接口写的(注意,在macOSX中已经标注为废除,头文件得换做sys/ucontext.h),结果就是我用了汇编来写,但是尽量不用汇编来写整个switch_to调度函数(这样有个明显的坏处,那就是用gas/n

  • C语言创建线程thread_create()的方法

    在头文件 threads.h 中,定义和声明了支持多线程的宏.类型和函数.所有直接与线程相关的标识符,均以前缀 thrd_ 作为开头.例如,thrd_t 是一个对象类型,它标识了一个线程. 函数 thrd_create()用于创建并开始执行一个新线程.函数 thrd_create()的其中一个参数为在新线程中需要被执行的函数 thrd_create()的其中一个参数为在新线程中需要被执行的函数.thrd_create()的完整原型是: int thrd_create(thrd_t *thr, t

  • 简单了解Java创建线程两种方法

    这篇文章主要介绍了简单了解Java创建线程两种方法,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下 Java实现并启动线程有两种方法 1.写一个类继承自Thread类,重写run方法.用start方法启动线程 2.写一个类实现Runnable接口,实现run方法.用new Thread(Runnable target).start()方法来启动 注意:start方法不是立即执行多线程,而是使得该线程变为就绪态(Runnable) 1.通过扩展Th

  • R语言创建矩阵的实现方法

    矩阵 向量vector用于描述一维数据,是R语言中最基础的数据结构形式 矩阵matrix可以描述二维数据,和向量相似,其内部元素可以是实数.复数.字符.逻辑型数据 矩阵包含行和列,分为单位矩阵.对角矩阵和普通矩阵.矩阵可以进行四则运算,以及进行求特征值.特征向量等运算 矩阵matrix使用两个下标来访问元素,A[i,j]表示矩阵A第i行.第j列的元素 矩阵创建--matrix函数 matrix函数创建矩阵,其格式为: matrix(data = NA,nrow = 1,ncol = 1,byro

  • 火遍全网的Hutool使用Builder模式创建线程池的方法

    前言 Builder 设计模式也叫做 构建者模式或者建造者模式,名字只是一种叫法,当聊起三种名称的时候知道是怎么回事就行 Builder 设计模式在作者编码过程中,属于比较常用的模式之一.优秀的设计模式总是会受到广大开发者的青睐,Hutool 也是其中之一 因为上周编写的业务需要用到线程池,就去 Hutool thread 包下看了看,还真有惊喜,学习到了一种之前编码中没用过的 Builder 模式实现 这里必须提一句:设计模式重要的是思想,一种设计模式可能不止一种实现方式 Builder 模式

  • 易语言创建EXCEL对象的方法

    Excel对于大家来说,肯定不会陌生,办公软件"三剑客"之一,报表利器.今天,我们要学习的是易语言怎么创建EXCEL对象,好了,言归正传吧! 1.老规矩,首先运行易语言,创建"Windows窗口程序",如图: 2.绘制按钮组件,调整其位置和大小.如图: 3.修改相关组件的对应属性,并规范命名组件的名称.如图: 4.编写程序代码,具体代码如下: 5.代码编写完成,测试程序.猛戳F5键,运行程序.如图:

  • 易语言创建Word对象的方法

    Word对象,就是平时我们所说的COM对象,我们使用的操作系统中有很多COM对象 1.首先,运行易语言程序,新建"Windows窗口程序"并进入.如图: 2.在创建的窗口上,绘制一个按钮组件,设置按钮组件的大小和位置.如图: 3.修改窗口和按钮的标题,并规范命名按钮组件的名称.如图: 4.编写程序代码,具体代码如下: 5.代码编写完成,测试程序.如图:

  • java实现/创建线程的几种方式小结

    进程与线程 进程可以简单理解成一个可执行程序例如.exe,在Windows中的任务管理器中可以查看每一个进程,进程是一次程序的执行,是程序在数据集合上运行的过程,是系统资源调度的一个单位.进程主要负责向操作系统申请资源.然而一个进程中,多个线程可以共享进程中相同的内存或文件资源.线程就是一个进程一个程序要完成所依赖的子任务,这些子任务便可以看作是一个线程. 第一种方式继承Thread类 从java源码可以看出Thread类本质上实现了Runnable接口的实例类,代表了线程的一个线程的实例,启动

  • Springboot 配置线程池创建线程及配置 @Async 异步操作线程池详解

    目录 前言 一.创建一个Springboot Web项目 二.新建ThreadPoolConfig 三.新建controller测试 四.演示结果 前言 众所周知,创建显示线程和直接使用未配置的线程池创建线程,都会被阿里的大佬给diss,所以我们要规范的创建线程. 至于 @Async 异步任务的用处是不想等待方法执行完就返回结果,提高软件前台响应速度,一个程序中会用到很多异步方法,所以需要使用线程池管理,防止影响性能. 一.创建一个Springboot Web项目 需要一个Springboot项

  • Java都有哪些创建线程的方法

    目录 1.继承Thread类 1.1 普通类继承Thread 1.2 匿名内部类 1.3 缺点分析 2.实现Runnable接口 2.1 普通类实现Runnable 2.2 匿名Runnable实现类 2.3 Lambda创建Runnable 2.4 缺点分析 3.使用Callable接口 3.1 普通类实现Callable 3.2 匿名Callable实现类 总结 在 Java 中,线程的创建方法有 7 种,分为以下 3 大类: 继承 Thread 类的方式,它有 2 种实现方法. 实现 Ru

  • java线程之用Thread类创建线程的方法

    在Java中创建线程有两种方法:使用Thread类和使用Runnable接口.在使用Runnable接口时需要建立一个Thread实例.因此,无论是通过Thread类还是Runnable接口建立线程,都必须建立Thread类或它的子类的实例.Thread类的构造方法被重载了八次,构造方法如下: 复制代码 代码如下: public Thread( ); public Thread(Runnable target); public Thread(String name); public Thread

随机推荐