Latest web development tutorials

C de la Multithreading

Multithreading est une forme spécialisée de multi-tâches, multi-tâches permet de laisser couler l'ordinateur deux ou plusieurs programmes. En général, deux types de multitâche: basés-fil basée sur les processus et.

  • programme multitâche basé sur les processus est exécuté en même temps.
  • multitâche à base de fil de traitement est l'exécution simultanée du même fragment de programme.

programme multithread contient deux ou plusieurs parties qui peuvent être exécutées simultanément. Un tel programme pour chaque partie est appelée un fil, chaque fil définit un chemin séparé de l'exécution.

C ++ ne comprend pas de support intégré pour les applications multi-thread. Au lieu de cela, il est totalement dépendant du système d'exploitation pour fournir cette fonctionnalité.

Ce tutoriel suppose que vous utilisez le système d'exploitation Linux, nous voulons utiliser POSIX écrire programme multithread C ++. API threads POSIX ou Pthreads peuvent être fournis sur plusieurs types de systèmes Unix POSIX disponibles, tels que FreeBSD, NetBSD, GNU / Linux, Mac OS X et Solaris.

Créer un fil

Le programme suivant, nous pouvons l'utiliser pour créer un POSIX threads:

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

Ici, pthread_create crée un nouveau thread et le rendre exécutable.Ce qui suit est une description des paramètres:

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

Quand un thread est créé avec succès, la fonction retourne 0 si la valeur de retour de 0 indique que n'a pas réussi à créer le thread.

Termine le fil

Utilisez la procédure suivante, nous pouvons l'utiliser pour mettre fin à un POSIX threads:

#include <pthread.h>
pthread_exit (status) 

Ici, pthread_exit utilisé pour quitter explicitement un fil.Dans des circonstances normales, la fonction pthread_exit () est appelée lorsque le travail sans avoir à continuer à exister après le fil.

Si la main () avant la fin du fil qu'il a créé, et sort par pthread_exit (), puis les autres threads continueront à exécuter. Sinon, ils seront dans la main () à la fin est automatiquement résilié.

Exemples

Le code simple exemple suivant utilise pthread_create () crée cinq fils, chaque sortie "Bonjour 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);
}

Utilisez la bibliothèque -lpthread compilé le programme suivant:

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

Maintenant, la mise en œuvre du programme produira les résultats suivants:

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

Le code simple exemple suivant utilise pthread_create () crée cinq fils, et de recevoir des paramètres entrants. Chaque thread imprime un "Bonjour w3big!" Message, et délivre les paramètres reçus, puis appelez pthread_exit () se termine le fil.

//文件名: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);
}

Maintenant, compiler et exécuter le programme produira les résultats suivants:

$ 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

Passer des paramètres à une discussion

Cet exemple montre comment passer des paramètres structure multi. Vous pouvez passer tout type de données dans le rappel de fil, car il pointe vers le vide, comme le montrent les exemples suivants:

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

Lorsque le code ci-dessus est compilé et exécuté, il produit les résultats suivants:

$ 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

Connexion et séparation de fil

Nous pouvons utiliser les deux fonctions suivantes pour connecter ou threads séparés:

pthread_join (threadid, status) 
pthread_detach (threadid) 

pthread_join () sous-programme entraver le programme appelant jusqu'à ce que le fil threadid spécifié se termine. Lorsque vous créez un thread, il est un attribut définit si elle est connectée (jumelables) ou amovible (individuelle). Définir seulement créer un thread qui peut être connecté peut être connecté. Si un thread est créé est défini comme séparables, il ne peut jamais être connecté.

Cet exemple montre comment utiliser la fonction pthread_join () pour attendre le fil d'achèvement.

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

Lorsque le code ci-dessus est compilé et exécuté, il produit les résultats suivants:

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.