IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

Threads & Processus C++ Discussion :

mauvaise synchronization des thread


Sujet :

Threads & Processus C++

  1. #1
    Membre averti
    Homme Profil pro
    Consultant en sécurité
    Inscrit en
    Août 2011
    Messages
    21
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Maroc

    Informations professionnelles :
    Activité : Consultant en sécurité
    Secteur : Services de proximité

    Informations forums :
    Inscription : Août 2011
    Messages : 21
    Par défaut mauvaise synchronization des thread
    bonjour,
    avant de poser ma question,je tiens à faire une petite description de mon code.
    je dispose d'une fonction qui me génere des elements,je passe ces elements à une fonction qui monte une socket et appele deux thread une pour récuperer les réponses du serveur,l'autre pour l'envoi des élements générés),jusqu'ici tout est bon,ce traitement(Séquentiel:1envoi à la fois) demeure lent,je désire le rendre rapide(dans cet exemple 2 envois à la fois) et du coup j'ai transformé la fonction qui monte la socket à son tour à une Thread,comme ça la fonction de génération peut génerer un lot d'elements et appeler plusieurs thread de montage de sockets qui à leur tour appelent les threads d'envoi et de reception sur chaque socket .


    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
     
    void generer(char* element1,char* element2,int i,int j)
    {
     
    HANDLE myhandle_send_it_via_socket_lot1;
    HANDLE myhandle_send_it_via_socket_lot2,
     
     struct thread_params_send send_params;
     
     
    element1=.....;//traitement des element1
    element2=.....;//traitement des element2
     
     
    while(condition)//tant kil y'a des elements à envoyer
          {
            cout <<"affichage";
            cout <<"affcihage";
     
           send_params.element1=element1;
           send_params.element2=element2;
     
    myhandle_send_it_via_socket_lot1 = (HANDLE)_beginthreadex(0, 0, &Send_it_via_socket, (void*)&send_params, 0, 0);
     
     
    element1=x;//transformation des elements generés
    element2=y;//transformation des elementsgenéres
     
    send_params.element1=element1;
    send_params.element2=element2;
     
    myhandle_send_it_via_socket_lot2 = (HANDLE)_beginthreadex(0, 0, &Send_it_via_socket, (void*)&send_params, 0, 0);
     
    WaitForSingleObject( myhandle_send_it_via_socket_lot1, INFINITE );
    WaitForSingleObject( myhandle_send_it_via_socket_lo2, INFINITE );
     
     
           }
     
     
     
    }
    donc je me trouve avec:

    générer()->thread send_it_via_socket_lot1->thread envoi socket
    générer()->thread send_it_via_socket_lot1->thread réception socket
    génerer()->thread_send_it_via_socket_lot2->thread envoi socket
    générer()->thread send_it_via_socket_lot2->thread réception socket

    question:
    a-les thread d'envoie et de reception socket affichent des résultant,donc j'ai un affichage en désordre et désagréable
    Comment améliorer cet affichage?

    b-lorsque je transforme:
    element1=x;//transformation des elements generés
    element2=y;//transformation des elementsgenéres
    on dirait que c'est la première thread avec le handle myhandle_send_it_via_socket_lot1 qui prend les valeurs changés malgré que je l'ai appelé avec les anciens valeur du parametre (void*)&send_params
    donc je me trouve obligé de mettre un waitforobjects avant la transformation des parametres,si j'attend thread send_it_via_socket_lot1 qu'elle termine ça veut dire que j'ai rien gagné.je me retrouve dans le régime séquentiel...(((((

    des suggestion sont la bienvenue.

  2. #2
    Membre Expert

    Homme Profil pro
    Développeur informatique
    Inscrit en
    Septembre 2007
    Messages
    1 895
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 49
    Localisation : France, Bouches du Rhône (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : High Tech - Opérateur de télécommunications

    Informations forums :
    Inscription : Septembre 2007
    Messages : 1 895
    Par défaut
    Citation Envoyé par halil.zakaria Voir le message
    bonjour,
    avant de poser ma question,je tiens à faire une petite description de mon code.
    je dispose d'une fonction qui me génere des elements,je passe ces elements à une fonction qui monte une socket et appele deux thread une pour récuperer les réponses du serveur,l'autre pour l'envoi des élements générés),jusqu'ici tout est bon,ce traitement(Séquentiel:1envoi à la fois) demeure lent,je désire le rendre rapide(dans cet exemple 2 envois à la fois) et du coup j'ai transformé la fonction qui monte la socket à son tour à une Thread,comme ça la fonction de génération peut génerer un lot d'elements et appeler plusieurs thread de montage de sockets qui à leur tour appelent les threads d'envoi et de reception sur chaque socket .


    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
     
    void generer(char* element1,char* element2,int i,int j)
    {
     
    HANDLE myhandle_send_it_via_socket_lot1;
    HANDLE myhandle_send_it_via_socket_lot2,
     
     struct thread_params_send send_params;
     
     
    element1=.....;//traitement des element1
    element2=.....;//traitement des element2
     
     
    while(condition)//tant kil y'a des elements à envoyer
          {
            cout <<"affichage";
            cout <<"affcihage";
     
           send_params.element1=element1;
           send_params.element2=element2;
     
    myhandle_send_it_via_socket_lot1 = (HANDLE)_beginthreadex(0, 0, &Send_it_via_socket, (void*)&send_params, 0, 0);
     
     
    element1=x;//transformation des elements generés
    element2=y;//transformation des elementsgenéres
     
    send_params.element1=element1;
    send_params.element2=element2;
     
    myhandle_send_it_via_socket_lot2 = (HANDLE)_beginthreadex(0, 0, &Send_it_via_socket, (void*)&send_params, 0, 0);
     
    WaitForSingleObject( myhandle_send_it_via_socket_lot1, INFINITE );
    WaitForSingleObject( myhandle_send_it_via_socket_lo2, INFINITE );
     
     
           }
     
     
     
    }
    donc je me trouve avec:

    générer()->thread send_it_via_socket_lot1->thread envoi socket
    générer()->thread send_it_via_socket_lot1->thread réception socket
    génerer()->thread_send_it_via_socket_lot2->thread envoi socket
    générer()->thread send_it_via_socket_lot2->thread réception socket

    question:
    a-les thread d'envoie et de reception socket affichent des résultant,donc j'ai un affichage en désordre et désagréable
    Comment améliorer cet affichage?

    b-lorsque je transforme:
    element1=x;//transformation des elements generés
    element2=y;//transformation des elementsgenéres
    on dirait que c'est la première thread avec le handle myhandle_send_it_via_socket_lot1 qui prend les valeurs changés malgré que je l'ai appelé avec les anciens valeur du parametre (void*)&send_params
    donc je me trouve obligé de mettre un waitforobjects avant la transformation des parametres,si j'attend thread send_it_via_socket_lot1 qu'elle termine ça veut dire que j'ai rien gagné.je me retrouve dans le régime séquentiel...(((((

    des suggestion sont la bienvenue.
    Sans le code des threads, ça me parait compliqué à vérifier, mais ou sont les synchronisations ?

    Tel que je le vois, tu réutilise la même structure pour stocker les données que tu envoie aux deux threads. Qui plus est, tu leur passe un pointeur sur cette structure. Du coup, il n'est pas anormal que les deux threads aient les même données à traiter (ou, quelques fois, des données différentes).

    Pour ce qui est des cout, je te rappelle que c'est un objet global. Du coup, si tu fais

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
     
    // thread 1
    cout << "aaaaaaaaaaaaaaaaaaaaa";
    // thread 2
    cout << "bbbbbbbbbbbbbbbbbbbbb";
    Rien ne te garanti que tu ne vas pas avoir quelque chose d'étrange comme ababababababbbabaabbaba... en sortie. Là aussi, il faut synchroniser les appels via une zone d'exclusion mutuelle (un mutex, pour faire simple).

    C++11 précise davantage le modèle de mémoire de C++ et propose les solutions pour palier aux problèmes d'accès concurrentiels à une donnée (ce qu'on appelle un data race). Tu peux te renseigner sur le sujet, histoire de comprendre un peu mieux (et si ton compilateur supporte std::thread, je te propose de l'utiliser, au lieu d'utiliser _beginthread/_beginthreadex ; tu va voir, ça sera plus simple .
    [FAQ des forums][FAQ Développement 2D, 3D et Jeux][Si vous ne savez pas ou vous en êtes...]
    Essayez d'écrire clairement (c'est à dire avec des mots français complets). SMS est votre ennemi.
    Evitez les arguments inutiles - DirectMachin vs. OpenTruc ou G++ vs. Café. C'est dépassé tout ça.
    Et si vous êtes sages, vous aurez peut être vous aussi la chance de passer à la télé. Ou pas.

    Ce site contient un forum d'entraide gratuit. Il ne s'use que si l'on ne s'en sert pas.

  3. #3
    Membre averti
    Homme Profil pro
    Consultant en sécurité
    Inscrit en
    Août 2011
    Messages
    21
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Maroc

    Informations professionnelles :
    Activité : Consultant en sécurité
    Secteur : Services de proximité

    Informations forums :
    Inscription : Août 2011
    Messages : 21
    Par défaut Threads
    une autre question,si j'appele la thread montage_socket_improvisé() à partir de ma fonction main_improvisé() 2 fois est ce que je vais me trouver avec 2 socket connectés à mon serveur,ou une seulement partagé entre les 2 threads.Merci
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
     
    main_improvisé()
    {
    HANDLE handle_thread,socket1,handle_thread,socket2;
    handle_thread,socket1 = (HANDLE)_beginthreadex(0, 0, &montage_socket_improvisé, (void*), 0, 0);
    handle_thread,socket2= (HANDLE)_beginthreadex(0, 0, &montage_socket_improvisé, (void*), 0, 0);
    }
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
     
    unsigned int __stdcall montage_socket_improvisé(void *)
    {
     
     
    SOCKET s;
    struct sockaddr_in server_address;
     
     
    s = socket(AF_INET, SOCK_STREAM, 0);  
     
    connect(s,(const struct sockaddr FAR *) &server_address,sizeo(SOCKADDR_IN))
     
    ZeroMemory(&server_address, sizeof(SOCKADDR_IN));
    server_address.sin_family = AF_INET;  
    server_address.sin_port = htons(SERVER_PORT);
    CopyMemory(&server_address.sin_addr, hp->h_addr_list[0], hp->h_length);
     
     
     
    return(1);

  4. #4
    Membre Expert

    Homme Profil pro
    Développeur informatique
    Inscrit en
    Septembre 2007
    Messages
    1 895
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 49
    Localisation : France, Bouches du Rhône (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : High Tech - Opérateur de télécommunications

    Informations forums :
    Inscription : Septembre 2007
    Messages : 1 895
    Par défaut
    Citation Envoyé par halil.zakaria Voir le message
    une autre question,si j'appele la thread montage_socket_improvisé() à partir de ma fonction main_improvisé() 2 fois est ce que je vais me trouver avec 2 socket connectés à mon serveur,ou une seulement partagé entre les 2 threads.Merci
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
     
    main_improvisé()
    {
    HANDLE handle_thread,socket1,handle_thread,socket2;
    handle_thread,socket1 = (HANDLE)_beginthreadex(0, 0, &montage_socket_improvisé, (void*), 0, 0);
    handle_thread,socket2= (HANDLE)_beginthreadex(0, 0, &montage_socket_improvisé, (void*), 0, 0);
    }
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
     
    unsigned int __stdcall montage_socket_improvisé(void *)
    {
     
     
    SOCKET s;
    struct sockaddr_in server_address;
     
     
    s = socket(AF_INET, SOCK_STREAM, 0);  
     
    connect(s,(const struct sockaddr FAR *) &server_address,sizeo(SOCKADDR_IN))
     
    ZeroMemory(&server_address, sizeof(SOCKADDR_IN));
    server_address.sin_family = AF_INET;  
    server_address.sin_port = htons(SERVER_PORT);
    CopyMemory(&server_address.sin_addr, hp->h_addr_list[0], hp->h_length);
     
     
     
    return(1);
    Tu crée deux threads, et tu leur dit d'exécuter le code de la fonction montage_socket_improvisé().

    Dans chaque thread, tu crée une socket et tu la connecte.

    Ce qui fait que tu crée deux sockets et que tu les connecte.

    Donc oui, nécessairement, tu auras deux connexions sur ton serveur.

    La programmation, ce n'est pas magique. Le programme fait ce que tu lui dit de faire, que tu soit en multithread ou non. Il ne partage pas par magie des informations entre deux threads : soit les informations sont partagées parce que que tu lui demande explicitement (comme dans le premier message), soit elles sont partagées parce qu'elles ne sont pas locales aux threads (par exemple une variable globale ou statique à une fonction).

    Le reste n'est pas partagé.

    Il semblerait que tu ais des problèmes pour comprendre certains concepts liés à la programmation concurrente. Puisque c'est crucial dans ton domaine d'écrire du code qui est sûr (vu que tu es consultant sécurité), il faut absolument que tu maîtrise ces concepts - sans quoi, tu va créer plus de problèmes que tu ne vas en résoudre, et tu risque fort d'augmenter la surface d'attaque de l'application que tu écrit.

    Puis-je te conseiller de lire le maximum de choses sur le sujet, y compris sur ce forum ou des livres un peu ancien comme "Win32 Multithread Programming" (http://shop.oreilly.com/product/9781565922969.do) (en anglais) ? Il me semble que c'est la chose à faire.
    [FAQ des forums][FAQ Développement 2D, 3D et Jeux][Si vous ne savez pas ou vous en êtes...]
    Essayez d'écrire clairement (c'est à dire avec des mots français complets). SMS est votre ennemi.
    Evitez les arguments inutiles - DirectMachin vs. OpenTruc ou G++ vs. Café. C'est dépassé tout ça.
    Et si vous êtes sages, vous aurez peut être vous aussi la chance de passer à la télé. Ou pas.

    Ce site contient un forum d'entraide gratuit. Il ne s'use que si l'on ne s'en sert pas.

Discussions similaires

  1. Réponses: 9
    Dernier message: 03/11/2014, 11h52
  2. Problème de modification des paramètres avec des threads synchrones
    Par manelhaj dans le forum Threads & Processus
    Réponses: 5
    Dernier message: 22/09/2013, 11h03
  3. [reseaux] Gestion des threads en perl
    Par totox17 dans le forum Programmation et administration système
    Réponses: 2
    Dernier message: 28/11/2002, 09h40
  4. Réponses: 3
    Dernier message: 04/09/2002, 09h42
  5. Programmer des threads
    Par haypo dans le forum C
    Réponses: 6
    Dernier message: 02/07/2002, 13h53

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo