Latest web development tutorials

C ++ Multithreading

Multithreading ist eine spezielle Form von Multi-Tasking ermöglicht Multi-Tasking dem Computer ausführen, zwei oder mehr Programme lassen. Im Allgemeinen werden zwei Arten von Multitasking: prozessbasierten und Gewindebasis.

  • Prozessbasiertes Multitasking Programm wird gleichzeitig ausgeführt.
  • Verarbeitungsthread-basierten Multitasking ist die gleichzeitige Ausführung des gleichen Programmfragment.

Multithreaded-Programm enthält zwei oder mehr Teile, die gleichzeitig ausgeführt werden können. Ein solches Programm für jedes Teil ist ein Thread genannt, definiert jeder Thread einen separaten Pfad der Ausführung.

C ++ enthält keine eingebaute Unterstützung für Multi-Threaded-Anwendungen. Stattdessen ist es völlig abhängig von dem Betriebssystem diese Funktionalität bereitzustellen.

Dieses Tutorial geht davon aus, dass Sie das Linux-Betriebssystem verwenden, wollen wir POSIX schreiben multithreaded C ++ Programm zu verwenden. API POSIX Threads oder Pthreads kann auf mehrere Arten von Unix-POSIX-Systemen zur Verfügung, wie FreeBSD, NetBSD, GNU / Linux, Mac OS X und Solaris zur Verfügung gestellt werden.

Erstellen Sie einen Faden

Das folgende Programm, können wir es verwenden, um eine POSIX-Threads zu erstellen:

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

Hier schafft pthread_create einen neuen Thread und es ausführbar zu machen.Nachfolgend finden Sie eine Beschreibung der Parameter:

参数 描述
thread 指向线程标识符指针。
attr 一个不透明的属性对象,可以被用来设置线程属性。您可以指定线程属性对象,也可以使用默认值 NULL。
start_routine 线程运行函数起始地址,一旦线程被创建就会执行。
arg 运行函数的参数。它必须通过把引用作为指针强制转换为 void 类型进行传递。如果没有传递参数,则使用 NULL。

Wenn ein Thread erfolgreich erstellt wird, gibt die Funktion 0, wenn der Rückgabewert von 0, dass Thread zu erstellen fehlgeschlagen anzeigt.

Beenden Sie den Faden

Verwenden Sie das folgende Verfahren, können wir es verwenden, um eine POSIX-Threads zu beenden:

#include <pthread.h>
pthread_exit (status) 

Hier verwendet pthread_exit explizit einen Thread zu beenden.Unter normalen Umständen wird pthread_exit () -Funktion aufgerufen wird, wenn der Auftrag nach dem Thread zu existieren, die durchgeführt fortzusetzen.

Wenn der main () vor dem Ende des Gewindes, die es erstellt und durch pthread_exit Exits (), dann werden die anderen Threads weiterhin auszuführen. Andernfalls werden sie am Ende in der main () sein wird automatisch beendet.

Beispiele

Das folgende einfache Beispiel-Code verwendet pthread_create () Funktion erzeugt fünf Fäden, jeder Ausgang "Hallo w3big!":

#include <iostream>
// 必须的头文件是
#include <pthread.h>

using namespace std;

#define NUM_THREADS 5

// 线程的运行函数
void* say_hello(void* args)
{
    cout << "Hello w3big!" << endl;
}

int main()
{
    // 定义线程的 id 变量,多个变量使用数组
    pthread_t tids[NUM_THREADS];
    for(int i = 0; i < NUM_THREADS; ++i)
    {
        //参数依次是:创建的线程id,线程参数,调用的函数,传入的函数参数
        int ret = pthread_create(&tids[i], NULL, say_hello, NULL);
        if (ret != 0)
        {
           cout << "pthread_create error: error_code=" << ret << endl;
        }
    }
    //等各个线程退出后,进程才结束,否则进程强制结束了,线程可能还没反应过来;
    pthread_exit(NULL);
}

Verwenden Sie -lpthread Bibliothek folgendes Programm zusammengestellt:

$ g++ test.cpp -lpthread -o test.o

Nun wird die Durchführung des Programms wird die folgenden Ergebnisse erzielt:

$ ./test.o
Hello w3big!
Hello w3big!
Hello w3big!
Hello w3big!
Hello w3big!

Das folgende einfache Beispiel-Code verwendet pthread_create () Funktion erstellt fünf Threads und eingehenden Parameter erhalten. Jeder Thread druckt ein "Hallo w3big!" Nachricht und gibt die empfangenen Parameter, und rufen Sie dann pthread_exit () beendet den Faden.

//文件名:test.cpp

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

using namespace std;

#define NUM_THREADS     5

void *PrintHello(void *threadid)
{  
   // 对传入的参数进行强制类型转换,由无类型指针变为整形数指针,然后再读取
   int tid = *((int*)threadid);
   cout << "Hello w3big! 线程 ID, " << tid << endl;
   pthread_exit(NULL);
}

int main ()
{
   pthread_t threads[NUM_THREADS];
   int indexes[NUM_THREADS];// 用数组来保存i的值
   int rc;
   int i;
   for( i=0; i < NUM_THREADS; i++ ){      
      cout << "main() : 创建线程, " << i << endl;
      indexes[i] = i; //先保存i的值
      // 传入的时候必须强制转换为void* 类型,即无类型指针        
      rc = pthread_create(&threads[i], NULL, 
                          PrintHello, (void *)&(indexes[i]));
      if (rc){
         cout << "Error:无法创建线程," << rc << endl;
         exit(-1);
      }
   }
   pthread_exit(NULL);
}

Nun kompilieren und das Programm ausführen wird die folgenden Ergebnisse erzielt:

$ g++ test.cpp -lpthread -o test.o
$ ./test.o
main() : 创建线程, 0
main() : 创建线程, 1
main() : 创建线程, 2
main() : 创建线程, 3
main() : 创建线程, 4
Hello w3big! 线程 ID, 4
Hello w3big! 线程 ID, 3
Hello w3big! 线程 ID, 2
Hello w3big! 线程 ID, 1
Hello w3big! 线程 ID, 0

Übergeben Sie Parameter zu einem Thema

Dieses Beispiel zeigt, wie mehrere Parameter-Struktur zu übergeben. Sie können jede Art von Daten in dem Thread Rückruf übergeben, weil es in die Leere Punkte, wie in den folgenden Beispielen gezeigt:

#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);
}

Wenn der obige Code kompiliert und ausgeführt wird, erzeugt es die folgenden Ergebnisse:

$ g++ -Wno-write-strings test.cpp -lpthread -o test.o
$ ./test.o
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

Anschließen und Trennen Gewinde

Wir können die folgenden zwei Funktionen verwenden, um eine Verbindung oder separate Threads:

pthread_join (threadid, status) 
pthread_detach (threadid) 

pthread_join () Unterprogramm behindern das aufrufende Programm, bis die angegebene threadid Thread beendet. Wenn Sie einen Thread zu erstellen, es ist ein Attribut definiert, ob es angeschlossen ist (zusammenstellbar) oder abnehmbar (freistehend). Definieren Sie nur einen Thread erstellen, die verbunden werden können, angeschlossen werden kann. Wenn ein Thread erzeugt wird definiert als trennbare, kann es nie angeschlossen werden.

Dieses Beispiel zeigt, wie pthread_join () Funktion zu verwenden, für die Fertigstellung Thread zu warten.

#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;

   // 初始化并设置线程为可连接的(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);
      }
   }

   // 删除属性,并等待其他线程
   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);
}

Wenn der obige Code kompiliert und ausgeführt wird, erzeugt es die folgenden Ergebnisse:

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 : 4  ...exiting 
Sleeping in thread 
Thread with id : 3  ...exiting 
Sleeping in thread 
Thread with id : 2  ...exiting 
Sleeping in thread 
Thread with id : 1  ...exiting 
Sleeping in thread 
Thread with id : 0  ...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.