设为首页 加入收藏

TOP

C++多线程编程(一)
2016-08-19 16:03:48 】 浏览:661
Tags:线程 编程

概述

OS:Raspbian

什么叫做多线程编程,大概意思就是说对多个任务同时进行控制,而且相互之间还需要协调。相信很多人和我一样在开始的时候,认为多线程编程是为了利用多核处理器,使程序运行的更快。但是,现在只要打开操作系统,那么肯定就不止一个任务在工作,所以,和多核没有什么关系。加快速度,从某种层面上来说的确有这个效果。但是,其作用的方式是不同的,有点懵?OK,我们一会再说。

在项目中,遇到了不少需要用到多线程编程的例子。有的是在C++库里需要用到,有的是在Java语言用到,包括开发安卓的过程中。像是在QT中,用到的库是QThread,在java中继承Thread类。在这里,我想用C++中的thread.h这个头文件里的函数来进行举例,这个头文件的方便移植且不需要增加其他的库。虽然,我目前实在Raspbian上面进行编程,但是可以保证在Linux平台下也可以正常运行,windows下mingw也是可以正常运行的,其他的自己试一下吧。

现在,先举几个在项目中用到多线程编程的例子吧。
1.armLinux的开发中,经常使用中断。(什么叫中断模式,百度百科:暂时停止当前程序的执行转而执行处理新情况的程序和执行过程。简单的来说:就是当运行到某处,暂停运行,直到从硬件处获得某个信号,比如说获得键盘某个键按下,以后有机会细讲)这时候,我们不可以让主进程暂停了,因为主进程还有其他操作。有时候,用到的中断程序不止一个。那么,就需要开多个线程每个中断都处于不同的线程当中,才能检测各个中断信号。
2.在开发安卓的过程中,有一些操作是不允许在主线程中进行操作。例如网络通信。其实也是可以理解的,网络通信大多都需要长时间操作,那么如果主线程已经在操作UI了,如果此时耗时太多在网络通信上面的话,UI的创建就会延迟,这样手机就会出现卡顿,我们的手机已经够卡的了,所以,安卓就不允许在主线程中进行网络通信。

多线程基本使用

创建两个线程,输出他们是第几个线程。

#include 
  
   
// 线程相关类,在类Unix下一般都有
#include 
   
     using namespace std; // 定义线程启动的函数 void* fun1(void* args) { cout << "This is first Thread!\n"; } void* fun2(void* args) { cout << "This is second Thread!\n"; } int main() { // 线程结构体 pthread_t pt1,pt2; // 创建线程,线程创建成功,返回值是0 if(pthread_create(&pt1,NULL,fun1,NULL) != 0) { cout << "Error in create first Thread!\n"; } if(pthread_create(&pt2,NULL,fun2,NULL) != 0) { cout << "Error in create second Thread!\n"; } //等待线程结束后,结束进程 pthread_exit(NULL); return 0; } 
   
  

注意:在这里编译的时候,需要在IDE中设置静态编译库。所以,我就直接用命令行来进行编译。

g++ -o thread0 thread0.cpp -lpthread
./thread0

大多数情况下会先输出第一个线程所要输出的内容,但是如果多次运行的话,会发现有时候线程二的内容会在线程一的内容出来前出现。OK,现在有三个问题了:
1.不是C++多线程编程吗,那么怎么在类里面使用呢?
2.怎么往线程里面传入参数呢?
3.如果我们必须要线程一完成以后再进行线程二,怎么办?

线程调用类中函数

如果线程调用类中的函数,那么必须将该函数生命为静态函数。
静态成员函数属于静态全局区,线程可以共享该区域。

#include 
  
   
// 线程相关类,在类Unix下一般都有
#include 
   
     using namespace std; // 定义一个类 class MyThread { private: public: // 定义线程启动的函数,必须是静态的 static void* fun1(void* args); static void* fun2(void* args); }; void* MyThread::fun1(void* args) { cout << "This is first Thread!\n"; } void* MyThread::fun2(void* args) { cout << "This is second Thread!\n"; } int main() { // 线程结构体 pthread_t pt1,pt2; // 创建线程,线程创建成功,返回值是0 if(pthread_create(&pt1,NULL,MyThread::fun1,NULL) != 0) { cout << "Error in create first Thread!\n"; } if(pthread_create(&pt2,NULL,MyThread::fun2,NULL) != 0) { cout << "Error in create second Thread!\n"; } //等待线程结束后,结束进程 pthread_exit(NULL); return 0; } 
   
  

命令其实和上面一样的:

g++ -o thread1 thread1.cpp -lpthread
./thread1

传入参数

现在,往里面传入参数来确定分别是哪个线程来调用的。

#include 
  
   
// 线程相关类,在类Unix下一般都有
#include 
   
     #include 
    
      using namespace std; // 定义一个类 class MyThread { public: // 定义线程启动的函数,必须是静态的 static void* fun(void* args); }; void* MyThread::fun(void* args) { cout << "This is " << *((string*) args) << " Thread!\n"; } int main() { // 线程结构体 pthread_t pt; string ss1,ss2; // 创建线程,线程创建成功,返回值是0 ss1 = "first"; if(pthread_create(&pt,NULL,MyThread::fun,(void*)&ss1) != 0) { cout << "Error in create first Thread!\n"; } ss2 = "second"; if(pthread_create(&pt,NULL,MyThread::fun,(void*)&ss2) != 0) { cout << "Error in create first Thread!\n"; } //等待线程结束后,结束进程 pthread_exit(NULL); return 0; } 
    
   
  

编译运行命令以后不写了,同上即可。
我们来看一下结果,结果有点奇怪。有时候是first在前,有时候second在前,这自然不用多说。但是还有一种情况是:段错误。所以,我们继续来控制一下每个线程运行的前后顺序。

线程控制

结束某个线程或者控制线程等待某个信号量

定义两个线程,两个线程启动,在第一次输入后,结束地一个线程,在第二次输入后,开始运行线程二中的实际内容。

#include 
  
   
#include 
   
     #include 
    
      using namespace std; // 定义第一个线程类 class MyThread0 { public: static bool run; // 定义线程启动的函数,必须是静态的 static void* fun(void* args); }; // 定义第二个线程类 class MyThread1 { public: static bool waitRun; // 定义线程启动的函数,必须是静态的 static void* fun(void* args); }; bool MyThread0::run = true; bool MyThread1::waitRun = true; void* MyThread0::fun(void* args) { int i = 0; while(run) { i = 1; // 执行的任务 } cout << i << endl; } void* MyThread1::fun(void* args) { while(waitRun); // 实际执行的任务 cout << "MyThread1 is OK!" << endl; } int main() { pthread_t pt; if(pthread_create(&pt,NULL,MyThread0::fun,NULL) != 0) { cout << "Error in create first Thread!\n"; } if(pthread_create(&pt,NULL,MyThread1::fun,NULL) != 0) { cout << "Error in create first Thread!\n"; } // 至此两个程序已经开始运行 getchar(); MyThread0::run = false; getchar(); MyThread1::waitRun = false; pthread_exit(NULL); return 0; } 
    
   
  

我用这个方法很长时间了,杀人越货之利器,好理解,没有额外的函数,而且无论语言都可以直接移植。但是毕竟不是个特别好的办法,而且如果两个线程共享一个数据,那么就一定要先锁定某个线程,然后准备好资源后才可以启动另外一个线程,太过麻烦。而且一直要陷在死循环里暂停程序也不像个事。(其实,我是从嵌入式里面学到的)其实,在学习操作系统/数据库原理中对于并发性操作,都是相当需要注意的,每个线程的先后都要控制好,而且需要注意数据的保护和读写,这时候我们就需要引入互斥锁机制。

等待某个线程结束再开始其他线程

我们首先来看一下程序,程序中最后有个函数pthread_exit,这里的意思是等所有子线程结束后,主线程结束,也就是说到这个函数程序将会结束,以后所有的语句都不会再执行。而且,还有个问题就是等待所有线程结束,根本无法判断个别线程结束。那么,我们可不可以先等待某个线程结束,再继续运行下一步呢?

#include 
  
   
#include 
   
     #include 
    
      using namespace std; void* change_value(void* args) { cout << "This thread value is " << *((int *)args) << endl; } int main() { int value1 = 1,value2 = 2; pthread_t pt1,pt2; int ret = pthread_create(&pt1, NULL, change_value, (void*)&value1); if(ret != 0) { cout << "pthread_create error:error_code=" << ret << endl; } //pthread_join的另外一个作用就是可以控制等待某个进程结束 pthread_join(pt1,NULL); ret = pthread_create(&pt2, NULL, change_value, (void*)&value2); if(ret != 0) { cout << "pthread_create error:error_code=" << ret << endl; } pthread_join(pt2,NULL); return 0; } 
    
   
  

获得线程结束信息

我们首先来看一下程序,程序中最后有个函数pthread_exit,这里的意思是等子线程结束后,主线程结束,也就是说到这个函数程序将会结束,以后所有的语句都不会再执行。OK,那么我们即使获得线程结束信息,也无法表示。那么我们吧这条语句去了,去了的话会发现有的线程还没有运行完成,程序就已经结束了,怎么解决?当然也可以估计一下时间然后等待,或者设置一个公共变量,然后在主线程中利用循环暂停,但是,我们这里用系统提供给我们的函数来进行操作。

#include 
  
   
#include 
   
     #include 
    
      using name
首页 上一页 1 2 下一页 尾页 1/2/2
】【打印繁体】【投稿】【收藏】 【推荐】【举报】【评论】 【关闭】 【返回顶部
上一篇C++泛型编程 下一篇STL算法(19)――for_each()和tr..

最新文章

热门文章

Hot 文章

Python

C 语言

C++基础

大数据基础

linux编程基础

C/C++面试题目