web-dev-qa-db-fra.com

Exemple simple de threading en C++

Quelqu'un peut-il publier un exemple simple de démarrage de deux threads (orientés objet) en C++. 

Je recherche des objets de threads C++ réels sur lesquels je peux étendre les méthodes d'exécution (ou quelque chose de similaire), par opposition à l'appel d'une bibliothèque de threads de style C.

Mise à jour - J'ai omis toute requête spécifique à un système d'exploitation dans l'espoir que celui qui répondrait répondrait avec des bibliothèques multi-plateformes à utiliser. Je ne fais que l'expliciter maintenant.

364
Zak

Créez une fonction que vous voulez que le thread exécute, par exemple:

void task1(std::string msg)
{
    std::cout << "task1 says: " << msg;
}

Créez maintenant l’objet thread qui appellera finalement la fonction ci-dessus de la manière suivante:

std::thread t1(task1, "Hello");

(Vous devez #include <thread> pour accéder à la classe std::thread)

Les arguments du constructeur sont la fonction que le thread va exécuter, suivie des paramètres de la fonction. Le fil est automatiquement lancé lors de la construction.

Si plus tard vous voulez attendre que le thread ait fini d'exécuter la fonction, appelez:

t1.join(); 

(Rejoindre signifie que le thread qui a appelé le nouveau thread attendra que le nouveau thread termine son exécution avant de poursuivre sa propre exécution).


Le code

#include <string>
#include <iostream>
#include <thread>

using namespace std;

// The function we want to execute on the new thread.
void task1(string msg)
{
    cout << "task1 says: " << msg;
}

int main()
{
    // Constructs the new thread and runs it. Does not block execution.
    thread t1(task1, "Hello");

    // Do other things...

    // Makes the main thread wait for the new thread to finish execution, therefore blocks its own execution.
    t1.join();
}

Plus d'informations sur std :: thread ici

  • Sur GCC, compilez avec -std=c++0x -pthread.
  • Cela devrait fonctionner pour tout système d'exploitation, dans la mesure où votre compilateur prend en charge cette fonctionnalité (C++ 11).
482
MasterMastic

Techniquement, un tel objet finira par être construit sur une bibliothèque de threads de style C, car C++ vient juste de spécifier un stock std::thread modèle en c ++ 0x, qui vient juste d'être cloué et qui n'a pas encore été implémenté. Le problème est quelque peu systémique. Techniquement, le modèle de mémoire c ++ existant n’est pas assez strict pour permettre une sémantique bien définie pour tous les cas «se produit avant». Hans Boehm a écrit un article sur le sujet il y a quelque temps et a joué un rôle déterminant dans l'élaboration de la norme c ++ 0x sur le sujet.

http://www.hpl.hp.com/techreports/2004/HPL-2004-209.html

Cela dit, il existe plusieurs bibliothèques de threads C++ inter-plateformes qui fonctionnent parfaitement dans la pratique. Les blocs de construction de threads Intel contiennent un objet tbb :: thread qui se rapproche beaucoup de la norme c ++ 0x et Boost a une bibliothèque boost :: thread qui en fait de même.

http://www.threadingbuildingblocks.org/

http://www.boost.org/doc/libs/1_37_0/doc/html/thread.html

En utilisant boost :: thread, vous obtiendrez quelque chose comme:

#include <boost/thread.hpp>

void task1() { 
    // do stuff
}

void task2() { 
    // do stuff
}

int main (int argc, char ** argv) {
    using namespace boost; 
    thread thread_1 = thread(task1);
    thread thread_2 = thread(task2);

    // do other stuff
    thread_2.join();
    thread_1.join();
    return 0;
}
76
Edward KMETT

Il existe également une bibliothèque POSIX pour les systèmes d'exploitation POSIX. Vérifier pour la compatibilité 

#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
#include <iostream>

void *task(void *argument){
      char* msg;
      msg = (char*)argument;
      std::cout<<msg<<std::endl;
}

int main(){
    pthread_t thread1, thread2;
    int i1,i2;
    i1 = pthread_create( &thread1, NULL, task, (void*) "thread 1");
    i2 = pthread_create( &thread2, NULL, task, (void*) "thread 2");

    pthread_join(thread1,NULL);
    pthread_join(thread2,NULL);
    return 0;

}

compiler avec -lpthread 

http://en.wikipedia.org/wiki/POSIX_Threads

18
Hohenheimsenberg

Voici un moyen plus robuste de créer un nombre arbitraire de threads (en C++ 11 ou plus récent):

#include <thread>
#include <iostream>
using namespace std;

void doSomething(int id) {
    cout << "Thread id = " << id;
}

/**
 * Spawns n threads
 */
void spawnThreads(int n)
{
    thread threads[n];
    // spawn n threads:
    for (int i = 0; i < n; i++) {
        threads[i] = thread(doSomething, i + 1);
    }

    for (auto& th : threads) {
        th.join();
    }
}
11
Caner

Lorsque vous recherchez un exemple de classe C++ qui appelle l'une de ses propres méthodes d'instance dans un nouveau thread, cette question se pose, mais nous n'avons pas pu utiliser ces réponses de cette façon. Voici un exemple qui fait ça:

Classe.h

class DataManager
{
public:
    bool hasData;
    void getData();
    bool dataAvailable();
};

Class.cpp

#include "DataManager.h"

void DataManager::getData()
{
    // perform background data munging
    hasData = true;
    // be sure to notify on the main thread
}

bool DataManager::dataAvailable()
{
    if (hasData)
    {
        return true;
    }
    else
    {
        std::thread t(&DataManager::getData, this);
        t.detach(); // as opposed to .join, which runs on the current thread
    }
}

Notez que cet exemple n'entre pas dans le mutex ou le verrouillage.

8
livingtech

Cela dépend en grande partie de la bibliothèque que vous décidez d'utiliser. Par exemple, si vous utilisez la bibliothèque wxWidgets, la création d'un fil ressemblerait à ceci:

class RThread : public wxThread {

public:
    RThread()
        : wxThread(wxTHREAD_JOINABLE){
    }
private:
    RThread(const RThread &copy);

public:
    void *Entry(void){
        //Do...

        return 0;
    }

};

wxThread *CreateThread() {
    //Create thread
    wxThread *_hThread = new RThread();

    //Start thread
    _hThread->Create();
    _hThread->Run();

    return _hThread;
}

Si votre thread principal appelle la méthode CreateThread, vous créerez un nouveau thread qui commencera à exécuter le code dans votre méthode "Entry". Vous devrez garder une référence au fil dans la plupart des cas pour le rejoindre ou l’arrêter . Plus d'infos ici: Documentation wxThread

7
LorenzCK

À moins de vouloir une fonction séparée dans les espaces de noms globaux, nous pouvons utiliser les fonctions lambda pour créer des threads. 

L'un des principaux avantages de la création de thread à l'aide de lambda est qu'il n'est pas nécessaire de transmettre des paramètres locaux sous forme de liste d'arguments. Nous pouvons utiliser la liste de capture pour la même chose et la propriété de fermeture de lambda prendra en charge le cycle de vie.

Voici un exemple de code

int main() {
    int localVariable = 100;

    thread th { [=](){
        cout<<"The Value of local variable => "<<localVariable<<endl;
    }}

    th.join();

    return 0;
}

De loin, j'ai trouvé que les lambdas C++ étaient le meilleur moyen de créer des threads, en particulier pour des fonctions de thread plus simples.

5
Daksh

// multithreaded.c ++: Exemple simple de threading en C++ utilisant le threading et la section critique.

#include "stdafx.h"
#include <thread>
#include <iostream>
#include<fstream>
#include <windows.h>

using namespace std;


bool flag = 1;
auto path = "D:\\temp";
void writestatus(int i, int j);
CRITICAL_SECTION cs;

void workerThread(int j)
{
    int i = 1;
    ofstream f2;
    char buff[150] = { 0 };
    while (flag)
    {
        sprintf_s(buff, 150, "D:\\temp\\MyTemp_%d%03d.txt", j, i++);

        //str.append("%d", i++);
        f2.open(buff);
        f2 << buff;
        f2.close();
        //Sleep(10);
    }
    EnterCriticalSection(&cs);
    writestatus(i, j);
    LeaveCriticalSection(&cs);
}

void writestatus(int i, int j)
{
    ofstream f1;
    char buff[150] = { 0 };
    f1.open("D:\\temp\\status.txt", ios_base::app);
    sprintf_s(buff, 150, "%d Writes %d files \n", j, i++);
    if (f1)
    {
        f1 << buff;
    }
    else
    {
        MessageBeep(1);
    }
    f1.close();
}

int main()
{
    system("del d:\\temp\\*.txt");

    InitializeCriticalSection(&cs);
    thread t1(workerThread, 1);
    thread t2(workerThread, 2);
    thread t3(workerThread, 3);
    thread t4(workerThread, 4);
    thread t5(workerThread, 5);

    Sleep(250);
    flag = 0;
    t1.join();
    t2.join();
    t3.join();
    t4.join();
    t5.join();
    return 0;
}
0
Anirudha Ketkar