位置:首頁 > 高級語言 > 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.