当前位置: 首页 > news >正文

我们如何控制调度 C、C++ 中的线程执行?

pic

🎬 Verdure陌矣:个人主页

🎉 个人专栏: 《C/C++》 | 《转载or娱乐》

🌾 种完麦子往南走,

感谢您的点赞、关注、评论、收藏、是对我最大的认可和支持!❤️


摘要:

  线程调度,内存管理在C/C++开发中是必不可少的,本文旨在通过C/C++的代码控制调度线程执行,前两个示例使用 C 语言编写,最后一个示例使用 C++ 语言编写。在第一种方法中,我使用了3个互斥锁和3个条件变量,在第二种方法中,使用全局变量作为控制器来控制线程,而第三个示例是用 C++ 编写的,使用的方法与第一个C示例中的方法相同。

关键词cc++线程调度

声明:本文作者原创,转载请附上文章出处与本文链接。

文章目录

      • 摘要:
        • Ⅰ.1 第一个示例
        • Ⅰ.2 第二个示例
        • Ⅱ.1 第三个示例

Ⅰ.1 第一个示例

  首先,查看 C 下面的第一个线程。这里它锁定了互斥锁 lock1(以便其他线程无法访问代码)开始执行(未添加代码,仅添加注释),最后在完成等待 cond1 的任务后,同样,第二个线程锁定了互斥锁 lock2,开始执行其业务逻辑,最后等待 cond2 的条件,第三个线程锁定了互斥锁 lock3,开始执行其业务逻辑,最后等待 cond3 的条件。

  我没有在这里添加任何业务逻辑,因为这只是一个例子。在注释掉的部分中,可以添加将以并行模式执行的业务逻辑。假设线程 3 依赖于线程 1 的最终输出(将插入表中),线程 3 将在创建其最终结果之前读取该信息,而线程 2 依赖于线程 3 的最终结果来生成其最终结果。因此,线程 1 在将数据插入表中后,通过条件变量向线程 3 发出信号,以继续其最终过程。这意味着线程 1 控制线程 3。由于线程 2 依赖于线程 3 的最终结果,因此线程 3 控制线程 2 的执行。在这里,我们可以允许线程 1 独立执行,因为它的操作不依赖于任何其他线程,但是对于线程控制,我们在这里要控制所有线程,因此,线程 1 由线程 2 控制。

  要启动控制过程,我们首先释放线程 1。在主线程(即主函数,每个程序都有一个主线程,在 C/C++ 中,一旦控制权通过内核传递给主方法/函数,此主线程将由操作系统自动创建)中,我们调用pthread_cond_signal(&cond1);。从主线程调用此函数后,等待条件 1 的线程 1 将被释放并开始进一步执行。完成最终任务后,它将调用pthread_cond_signal(&cond3);。现在,等待条件 3 的线程(即线程 3)将被释放,并开始执行其最后阶段,并将调用pthread_cond_signal(&cond2); 它将释放等待条件 2 的线程(在本例中为线程 2)。这是我们在多线程环境中调度和控制线程执行的方式。

#include<pthread.h>

pthread_cond_t cond1 = PTHREAD_COND_INITIALIZER;
pthread_cond_t cond2 = PTHREAD_COND_INITIALIZER;
pthread_cond_t cond3 = PTHREAD_COND_INITIALIZER;
pthread_mutex_t lock1 = PTHREAD_MUTEX_INITIALIZER;
pthread_mutex_t lock2 = PTHREAD_MUTEX_INITIALIZER;
pthread_mutex_t lock3 = PTHREAD_MUTEX_INITIALIZER;

int TRUE = 1;

void print(char *p)
{
  printf("%s",p);
}

void * threadMethod1(void *arg)
{
  printf("In thread1\n");
  do{
    pthread_mutex_lock(&lock1);
    //Add your business logic(parallel execution codes)  here
    pthread_cond_wait(&cond1, &lock1);
    printf("I am thread1  generating the final report and inserting into a table \n");
    pthread_cond_signal(&cond3);/* Now allow 3rd thread to process */
    pthread_mutex_unlock(&lock1);
  }while(TRUE);
  pthread_exit(NULL);
}

void * threadMethod2(void *arg)
{
  printf("In thread2\n");
  do
  {
    pthread_mutex_lock(&lock2);
    //Add your business logic(parallel execution codes)  here
    pthread_cond_wait(&cond2, &lock2);
    printf("I am thread2  generating the final report and inserting into a table \n");
    pthread_cond_signal(&cond1);
    pthread_mutex_unlock(&lock2);
  }while(TRUE);
  pthread_exit(NULL);
}

void * threadMethod3(void *arg)
{
  printf("In thread3\n");
  do
  {
    pthread_mutex_lock(&lock3);
    //Add your business logic(parallel execution codes)  here
    pthread_cond_wait(&cond3, &lock3);
    printf("I am thread3  generating the final report and inserting into a table \n");
    pthread_cond_signal(&cond2);
    pthread_mutex_unlock(&lock3);
  }while(TRUE);
  pthread_exit(NULL);
}

int main(void)
{
  pthread_t tid1, tid2, tid3;
  int i = 0;

  printf("Before creating the threads\n");
  if( pthread_create(&tid1, NULL, threadMethod1, NULL) != 0 )
        printf("Failed to create thread1\n");
  if( pthread_create(&tid2, NULL, threadMethod2, NULL) != 0 )
        printf("Failed to create thread2\n");
  if( pthread_create(&tid3, NULL, threadMethod3, NULL) != 0 )
        printf("Failed to create thread3\n");
    
  pthread_cond_signal(&cond1);/* Now allow first thread to process first */


  sleep(1);
  TRUE = 0;/* Stop all the thread */
  sleep(3);

 /* this is how we join thread before exit from a system */
  /*  
  pthread_join(tid1,NULL);
  pthread_join(tid2,NULL);
  pthread_join(tid3,NULL);*/

 exit(0);
}
Ⅰ.2 第二个示例

  在 C 第二种方法中,我使用全局变量 controller 作为控制器来控制线程。请仔细观察下面的示例,看看它是如何基于全局变量进行调度/控制的。但更好的方法是第一个例子,下面的内容只是为了理解,逻辑主要观察 while 循环内的“if 条件”即可,此程序的运行顺序为线程 3 -》线程 1 -》线程 2。

#include<pthread.h>

int controller = 0;

void print(char *p)
{
  printf("%s",p);
}

void * threadMethod1(void *arg)
{
  while(1)
  {
    if(controller == 3)
      break;
  }
  print("I am thread 1st\n");
  controller = 1;
  pthread_exit(NULL);
}

void * threadMethod2(void *arg)
{
  while(1)
  {
    if(controller == 1)
      break;
  }
  print("I am thread 2nd\n");
  controller = 2;
  pthread_exit(NULL);
}

void * threadMethod3(void *arg)
{
  while(1)
  {
    if(controller == 0)
      break;
  }
  print("I am thread 3rd\n");
  controller = 3;
  pthread_exit(NULL);
}

int main(void)
{
  pthread_t tid1, tid2, tid3;
  int i = 0;

  printf("Before creating the threads\n");
  if( pthread_create(&tid1, NULL, threadMethod1, NULL) != 0 )
        printf("Failed to create thread1\n");
  if( pthread_create(&tid2, NULL, threadMethod2, NULL) != 0 )
        printf("Failed to create thread2\n");
   sleep(3);
  if( pthread_create(&tid3, NULL, threadMethod3, NULL) != 0 )
        printf("Failed to create thread3\n");
 /*
  pthread_join(tid1,NULL);
  pthread_join(tid2,NULL);
  pthread_join(tid3,NULL);*/
  sleep(10);
 exit(0);
}
Ⅱ.1 第三个示例

  现在,我的第三个示例是用 C++ 编写的,这里使用的方法与第一个 C 示例中的方法相同,如果你直接看到这个示例,请阅读用 C 编写的第一个示例以了解该方法。下面的示例是在 Visual Studio 2013 中开发的代码,并且没有将代码分发到单独的头文件和 CPP 文件中。此外,我已经以内联方式声明和定义了所有方法,因为这仅仅是一个例子。此外,您可能会想,“为什么我要声明三个类,而类结构却是相同的?”不要混淆,我使用相同的类定义只是为了举例。查看业务逻辑的注释行,这里,每个类都有不同的业务功能和逻辑。这个例子针对的是三个不同的线程和三个不同的类,假设所有的类都是不同的,具有不同的功能和业务逻辑。

#include "stdafx.h"//remove this header file if you are compiling with different compiler
#include <thread>
#include <mutex>
#include <condition_variable>
#include <iostream>
#include "windows.h"//remove this header file if you are compiling with different compiler

std::condition_variable _tcond1;
std::condition_variable _tcond2;
std::condition_variable _tcond3;

class SimpleThread1
{
private:
    std::mutex  _lockprint;
    bool isThreadAlive = true;

public:
    SimpleThread1(){}
    SimpleThread1(SimpleThread1 &st){};

    void StartProcessing()
    {
        std::unique_lock<std::mutex> locker(_lockprint);
                  //Add your business logic(parallel execution codes)  here
        _tcond1.wait(locker);
        std::cout << "I am thread :1"<<std::endl;
        _tcond3.notify_one();
    }
    void operator()()
    {
        while (isThreadAlive)
            StartProcessing();
    }

    void stopeThread()
    {
    	isThreadAlive = false;
    }
};

class SimpleThread2
{
private:
    std::mutex  _lockprint;
    bool isThreadAlive = true;

public:
    SimpleThread2(){}
    SimpleThread2(SimpleThread2 &st) {};

    void StartProcessing()
    {
        std::unique_lock<std::mutex> locker(_lockprint);
                      //Add your business logic(parallel execution codes)  here
        _tcond2.wait(locker);
        std::cout << "I am thread :2"<< std::endl;
        _tcond1.notify_one();
    }
    void operator()()
    {
        while (isThreadAlive)
       		StartProcessing();
    }

    void stopeThread()
    {
    	isThreadAlive = false;
    }
};


class SimpleThread3
{
private:
    std::mutex  _lockprint;
    bool isThreadAlive = true;

public:
    SimpleThread3(){}
    SimpleThread3(SimpleThread3 &st) {};

    void StartProcessing()
    {
        std::unique_lock<std::mutex> locker(_lockprint);
        //Add your business logic(parallel execution codes)  here
        _tcond3.wait(locker);
        std::cout << "I am thread :3"<< std::endl;
        _tcond2.notify_one();
    }
    void operator()()
    {
        while (isThreadAlive)
        	StartProcessing();
    }

    void stopeThread()
    {
    	isThreadAlive = false;
    }
};

int main()
{
    SimpleThread1 st1;
    SimpleThread2 st2;
    SimpleThread3 st3;
    std::thread t1(st1);
    std::thread t2(st2);
    std::thread t3(st3);
    _tcond1.notify_one();
    t1.detach();
    t2.detach();
    t3.detach();
    Sleep(1000);//replace it with sleep(10) for linux/unix
    st1.stopeThread();
    st2.stopeThread();
    st3.stopeThread();
    return 0;
}

end~

http://www.dtcms.com/a/122636.html

相关文章:

  • HTTP 压力测试工具autocannon(AI)
  • 琴键上的强化学习:让机器人在真实世界里弹钢琴!
  • Spring如何实现资源文件的加载
  • 网络安全之-信息收集
  • 国内协作机器手焊接领域领军人物分析
  • MCP 实战系列(Day 2)- 动手搓个文件系统 MCP 服务器
  • Linux系统管理与编程12: FTP服务配置
  • 《DataX 安装与简单使用指南》
  • 计算机视觉中的基于网格的卷绕算法全解析
  • Ansible(6)——管理变量
  • TDengine 数据模型设计:多列模式与单列模式对比(一)
  • UE5 matcap学习笔记
  • 单片机领域中哈希表
  • 基于 SpringBoot音乐网站与分享平台
  • 设计模式-命令模式详解
  • 大数据学习(104)-clickhouse与hdfs
  • Python web程序在服务器上面部署详细步骤
  • Java延迟队列
  • 铼赛智能Edge mini斩获2025法国设计大奖 | 重新定义数字化齿科美学
  • 深入解析 C++ 设计模式:原理、实现与应用
  • YOLOv12即插即用--CPAM
  • 【Kafka基础】消费者命令行完全指南:从基础到高级消费
  • 软考高级-系统架构设计师 案例题-软件架构设计
  • vue:前端预览 / chrome浏览器设置 / <iframe> 方法预览 doc、pdf / vue-pdf 预览pdf
  • 蓝桥杯 一年中的第几天(日期问题)
  • 如何运用浏览器进行各种调试?(网络、内存、控制台等调试用法)
  • 前端实战:基于Vue3与免费满血版DeepSeek实现无限滚动+懒加载+瀑布流模块及优化策略
  • Vert.x vs. Micronaut:2025年高并发Java框架选型指南
  • redisson常用加锁方式
  • 【代码模板】判断C语言中文件是否存在?错误:‘F_OK’未声明如何处理?(access;#include “unistd.h“)