位置:首页 > 高级语言 > C++在线教程 > C++多线程

C++多线程

多线程多任务处理是一种特殊形式和多任务处理的功能,可以让电脑同时运行两个或两个以上的程序。在一般情况下,有两种类型的多任务:基于进程和基于线程。

基于进程的多任务处理程序的并发执行。基于线程的多任务处理的同一程序的片的并行执行。

多线程程序中包含可以同时运行两个或多个部分。这样的程序中的每个部分称为一个线程,每个线程限定一个单独的执行路径。

C++不包含多线程应用程序的任何内置支持。相反,它完全依赖于操作系统来提供此功能。

本在线教程假设正在使用的是Linux操作系统,我们要编写C++多线程使用POSIX程序。 POSIX线程或Pthreads提供的API,它可在多种Unix类POSIX系统如FreeBSD,NetBSD,GNU/Linux,Mac OS X和Solaris操作系统。

创建线程:

有下面的程序,我们使用它来创建一个POSIX线程:

#include <pthread.h>
pthread_create (thread, attr, start_routine, arg) 

在这里,pthread_create创建一个新的线程,并使其可执行文件。这个例程可以调用任何次数在代码内的任何地方。这里是参数的说明:

参数 描述
thread 一个不透明的,唯一的标识符由子程序返回的新线程
attr 一个不透明的属性对象可以被用来设置线程属性。可以指定一个线程属性对象,或NULL默认值
start_routine 在C++程序,一旦线程它被创建的将执行
arg 传递给一个start_routine参数。它必须通过引用作为指针转换void类型的传递。如果没有参数,那么要传递NULL

线程可由一个过程来创建的最大数目是依赖于实现的。一旦创建,线程是同行的而且可能会创建其他线程。有线程之间没有隐含层次或依赖。

终止线程:

有下面的程序,我们使用于终止POSIX线程:

#include <pthread.h>
pthread_exit (status) 

此处pthread_exit用于显式地退出一个线程。通常情况下,pthread_exit()函数被调用后,线程已完成其工作,并存在已不再需要。

如果main()中已创建线程之前完成,并退出使用了pthread_exit(),其他线程将继续执行。否则它们将自动在main()结束时终止。

例子:

这个简单的示例代码创建了5个线程使用pthread_create()函数。每个线程打印“Hello World!”通过调用消息,然后调用pthread_exit()终止。

#include <iostream>
#include <cstdlib>
#include <pthread.h>

using namespace std;

#define NUM_THREADS     5

void *PrintHello(void *threadid)
{
   long tid;
   tid = (long)threadid;
   cout << "Hello World! Thread ID, " << tid << endl;
   pthread_exit(NULL);
}

int main ()
{
   pthread_t threads[NUM_THREADS];
   int rc;
   int i;
   for( i=0; i < NUM_THREADS; i++ ){
      cout << "main() : creating thread, " << i << endl;
      rc = pthread_create(&threads[i], NULL, 
                          PrintHello, (void *)i);
      if (rc){
         cout << "Error:unable to create thread," << rc << endl;
         exit(-1);
      }
   }
   pthread_exit(NULL);
}

使用-lpthread库如下编译下面的程序:

$gcc test.cpp -lpthread

现在,执行程序,应该产生结果如下:

main() : creating thread, 0
main() : creating thread, 1
main() : creating thread, 2
main() : creating thread, 3
main() : creating thread, 4
Hello World! Thread ID, 0
Hello World! Thread ID, 1
Hello World! Thread ID, 2
Hello World! Thread ID, 3
Hello World! Thread ID, 4

传递参数给线程:

这个例子说明如何通过结构传递多个参数。可以通过任何数据类型在一个线程回调,因为它指向无效如下面的例子来说明:

#include <iostream>
#include <cstdlib>
#include <pthread.h>

using namespace std;

#define NUM_THREADS     5

struct thread_data{
   int  thread_id;
   char *message;
};

void *PrintHello(void *threadarg)
{
   struct thread_data *my_data;

   my_data = (struct thread_data *) threadarg;

   cout << "Thread ID : " << my_data->thread_id ;
   cout << " Message : " << my_data->message << endl;

   pthread_exit(NULL);
}

int main ()
{
   pthread_t threads[NUM_THREADS];
   struct thread_data td[NUM_THREADS];
   int rc;
   int i;

   for( i=0; i < NUM_THREADS; i++ ){
      cout <<"main() : creating thread, " << i << endl;
      td[i].thread_id = i;
      td[i].message = "This is message";
      rc = pthread_create(&threads[i], NULL,
                          PrintHello, (void *)&td[i]);
      if (rc){
         cout << "Error:unable to create thread," << rc << endl;
         exit(-1);
      }
   }
   pthread_exit(NULL);
}

让我们编译和运行上面的程序,这将产生以下结果:

main() : creating thread, 0
main() : creating thread, 1
main() : creating thread, 2
main() : creating thread, 3
main() : creating thread, 4
Thread ID : 3 Message : This is message
Thread ID : 2 Message : This is message
Thread ID : 0 Message : This is message
Thread ID : 1 Message : This is message
Thread ID : 4 Message : This is message

加入和卸下线程:

有以下两个程序,我们可以用它来连接或分离线程:

pthread_join (threadid, status) 
pthread_detach (threadid) 

pthread_join()将子程序模块调用线程,直到指定线程标识线程终止。当创建一个线程,其属性定义是否是可连接或分离。只有创建为可连接线可以连接。如果作为独立创建一个线程,它永远不能加入。

这个例子演示了如何使用 Pthread 加入例程等待线程的完成。

#include <iostream>
#include <cstdlib>
#include <pthread.h>
#include <unistd.h>

using namespace std;

#define NUM_THREADS     5

void *wait(void *t)
{
   int i;
   long tid;

   tid = (long)t;

   sleep(1);
   cout << "Sleeping in thread " << endl;
   cout << "Thread with id : " << tid << "  ...exiting " << endl;
   pthread_exit(NULL);
}

int main ()
{
   int rc;
   int i;
   pthread_t threads[NUM_THREADS];
   pthread_attr_t attr;
   void *status;

   // Initialize and set thread joinable
   pthread_attr_init(&attr);
   pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE);

   for( i=0; i < NUM_THREADS; i++ ){
      cout << "main() : creating thread, " << i << endl;
      rc = pthread_create(&threads[i], NULL, wait, (void *)i );
      if (rc){
         cout << "Error:unable to create thread," << rc << endl;
         exit(-1);
      }
   }

   // free attribute and wait for the other threads
   pthread_attr_destroy(&attr);
   for( i=0; i < NUM_THREADS; i++ ){
      rc = pthread_join(threads[i], &status);
      if (rc){
         cout << "Error:unable to join," << rc << endl;
         exit(-1);
      }
      cout << "Main: completed thread id :" << i ;
      cout << "  exiting with status :" << status << endl;
   }

   cout << "Main: program exiting." << endl;
   pthread_exit(NULL);
}

让我们编译和运行上面的程序,这将产生以下结果:

main() : creating thread, 0
main() : creating thread, 1
main() : creating thread, 2
main() : creating thread, 3
main() : creating thread, 4
Sleeping in thread
Thread with id : 0 .... exiting
Sleeping in thread
Thread with id : 1 .... exiting
Sleeping in thread
Thread with id : 2 .... exiting
Sleeping in thread
Thread with id : 3 .... exiting
Sleeping in thread
Thread with id : 4 .... exiting
Main: completed thread id :0  exiting with status :0
Main: completed thread id :1  exiting with status :0
Main: completed thread id :2  exiting with status :0
Main: completed thread id :3  exiting with status :0
Main: completed thread id :4  exiting with status :0
Main: program exiting.