感谢您的点赞、关注、评论、收藏、是对我最大的认可和支持!❤️
摘要:
线程调度,内存管理在C/C++开发中是必不可少的,本文旨在通过C/C++的代码控制调度线程执行,前两个示例使用 C 语言编写,最后一个示例使用 C++ 语言编写。在第一种方法中,我使用了3个互斥锁和3个条件变量,在第二种方法中,使用全局变量作为控制器来控制线程,而第三个示例是用 C++ 编写的,使用的方法与第一个C示例中的方法相同。
关键词
: c,c++,线程调度
声明:
本文作者原创,转载请附上文章出处与本文链接。
文章目录
- 摘要:
- Ⅰ.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) herepthread_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) herepthread_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) herepthread_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 compilerstd::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/unixst1.stopeThread();st2.stopeThread();st3.stopeThread();return 0;
}
end~