2010-04-30 5 views
4

J'apprends la programmation en utilisant pthreads. Comment écrire un programme pour imprimer des nombres impairs et des nombres pairs sur des threads séparés.programme pour imprimer des nombres impairs et des nombres pairs sur des threads séparés

+0

La sortie doit être 1,2,3 ..... Mais les nombres impairs et les nombres pairs doivent être imprimés sur des fils séparés. – user329013

+0

Vous ne pouvez pas garantir dans quel ordre la sortie de deux threads différents apparaîtra, sauf si vous utilisez un mutex. – QuantumPete

+0

@QuantumPete - un mutex ne garantit pas la commande. Lorsque le thread A libère le mutex, il n'y a aucune garantie que le thread B sera réveillé avant que le thread A le demande à nouveau. –

Répondre

1

Passez une valeur d'indicateur pour indiquer si le thread doit imprimer un nombre impair ou un nombre pair via l'argument de fonction de fil. En fonction de la même chose, commencez par 0 (pour les nombres pairs) ou 1 (pour les nombres impairs) et continuez à incrémenter de 2 dans les fils et imprimez.

Vous pouvez également imprimer l'ID de fil avec le numéro pour indiquer quel fil imprime quoi. Je suppose que vous savez comment utiliser pthreads.

[Mise à jour]: Lien pour pthreads Même avec l'utilisation de sémaphores ou mutex, il est difficile pour vous d'obtenir la sortie afin de 1,2,3 etc que vous ne savez jamais quel thread sera la chance de exécuter en premier. Pour cela, vous devrez peut-être utiliser des concepts avancés tels que la priorité de thread ou la communication entre threads à l'aide de variables conditionnelles. Ce ne sont que des indices. J'espère que si vous passez par le lien, vous obtiendrez plus d'informations.

+0

J'apprends des pthreads ... La solution que je cherchais était la synchronisation de fil utilisant des sémaphores. La production devrait être 1,2,3 ..... Mais les nombres impairs et les nombres pairs devraient être imprimés sur des threads séparés. Il serait utile si quelqu'un peut fournir les détails de l'utilisation. Aussi tout lien pour étudier pthreads. – user329013

6

Vous avez besoin de deux objets de synchronisation, tels qu'un sémaphore ou une variable de condition. L'idée est que le thread A demande au sémaphore A avant d'imprimer et de relâcher le sémaphore B après que le thread B fasse le contraire. L'idée est que, après que le thread A ait demandé le sémaphore A, il laissera tomber le sémaphore à 0. La prochaine fois qu'il demandera le sémaphore A, il bloquera jusqu'à ce que le thread B libère le sémaphore.

Dans le code pseudo, cela ressemble à:

initialization: 
    // set semA to 1 so that the call to sem_wait in the 
    // even thread will succeed right away 
    sem_init(semA, 1) 
    sem_init(semB, 0) 

even_thread: 
    to_print = 0; 

    loop: 
     sem_wait(semA); 

     write(to_print); 
     to_print += 2 

     sem_post(semB) 

odd_thread: 
    to_print = 1 

    loop: 
     sem_wait(semB) 

     write(to_print) 
     to_print += 2 

     sem_post(semA) 

Puisque vous voulez vous enseigner la programmation des fils, je vais laisser à vous convertir en code pthreads réelle.

+0

+1. Cette réponse est bonne. Cela a complètement sauté l'esprit. :) – Jay

+0

+1 pour enseigner à pêcher :) –

-1

en JAVA ...

public class EvenOddGenTest { 

/** 
* @param args 
*/ 
public static void main(String[] args) { 

NumberGenerator numGenerator = new NumberGenerator(); 

OddGenerator oddGen = new OddGenerator(numGenerator); 
EvenGenerator evenGen = new EvenGenerator(numGenerator); 

oddGen.start(); 
evenGen.start(); 

} 

} 
------------------ 

public class OddGenerator extends Thread { 

public NumberGenerator numGen; 

public OddGenerator(NumberGenerator numberGen) { 
this.numGen = numberGen; 
} 

public void run() { 
int i = 1; 
while (i <= 9) { 

numGen.printOdd(i); 
i = i + 2; 
} 
} 

} 

---- 

public class EvenGenerator extends Thread { 

public NumberGenerator numGen; 

public EvenGenerator(NumberGenerator numberGen) { 
this.numGen = numberGen; 
} 

public void run() { 
int i = 2; 
while (i <= 10) { 
numGen.printEven(i); 
i = i + 2; 
} 
} 
} 
------ 


public class NumberGenerator { 

boolean oddPrinted = false; 

public synchronized void printOdd(int number) { 

while (oddPrinted == true) { 
try { 
wait(); 

} catch (InterruptedException e) { 

} 
} 

System.out.println("NumberGenerator.printOdd() " + number); 
oddPrinted = true; 
notifyAll(); 

} 

public synchronized void printEven(int number) { 
while (oddPrinted == false) { 
try { 
wait(); 

} catch (InterruptedException e) { 

} 
} 

oddPrinted = false; 
System.out.println("NumberGenerator.printEven() " + number); 
notifyAll(); 
} 
} 

-------- 
+0

[Ceci a été signalé par SO comme "réponse tardive à une vieille question, fournie par un nouvel utilisateur.] Ce commentaire porte sur pthreads. , une réponse Java n'est pas particulièrement adaptée. Veuillez la supprimer. – danfuzz

3

Je pense en utilisant une variable conditionnelle et un mutex pourrait résoudre ce problème.

 

    pthread_mutex_t count_mutex  = PTHREAD_MUTEX_INITIALIZER; 
    pthread_cond_t condition_var = PTHREAD_COND_INITIALIZER; 

    void *functionCount1(); 
    void *functionCount2(); 

    int count = 0; 
    #define COUNT_DONE 200 

    main() 
    { 
     pthread_t thread1, thread2; 

     pthread_create(&thread1, NULL, &functionCount1, NULL); 
     pthread_create(&thread2, NULL, &functionCount2, NULL); 

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

     exit(0); 
    } 

    // Print odd numbers 

    void *functionCount1() 
    { 
     for(;;) 
     { 

      // Lock mutex and then wait for signal to relase mutex 
      pthread_mutex_lock(&count_mutex); 


      // Check if the last emitted value was an odd; if so, wait till 
      // an even is printed 
      if (count % 2 != 0) { 
       pthread_cond_wait(&condition_var, &count_mutex); 
      } 

      count++; 
      printf("Counter value functionCount1: %d\n",count); 
      pthread_cond_signal(&condition_var); 

      if(count >= COUNT_DONE) { 
      pthread_mutex_unlock(&count_mutex); 
      return(NULL); 
      } 
      pthread_mutex_unlock(&count_mutex); 
     } 
    } 


    // print even numbers 
    void *functionCount2() 
    { 
     for(;;) 
     { 

      // Lock mutex and then wait for signal to relase mutex 
      pthread_mutex_lock(&count_mutex); 

      // Check if the last emitted value was an even; if so, wait till 
      // an odd is printed 
      if (count % 2 == 0) { 
       pthread_cond_wait(&condition_var, &count_mutex); 
      } 

      count++; 
      printf("Counter value functionCount2: %d\n",count); 

      pthread_cond_signal(&condition_var); 

      if(count >= COUNT_DONE) { 
      pthread_mutex_unlock(&count_mutex); 
      return(NULL); 
      } 
      pthread_mutex_unlock(&count_mutex); 
     } 
    } 

    Output:: 
    ubuntu:~/work$ gcc even_odd.c -lpthread 
    ubuntu:~/work$ ./a.out 
    Counter value functionCount1: 1 
    Counter value functionCount2: 2 
    Counter value functionCount1: 3 
    Counter value functionCount2: 4 
    Counter value functionCount1: 5 
    Counter value functionCount2: 6 
    Counter value functionCount1: 7 
    Counter value functionCount2: 8 
    Counter value functionCount1: 9 
    Counter value functionCount2: 10 
    ... 

+0

Je ne l'ai pas vraiment compris, quand le compte est initialement 0, cette condition if (count% 2! = 0) échouerait et il n'y a pas d'appel à pthread_cond_wait (& condition_var, & count_mutex) ;. Plus tard le compte ++ est incrémenté et pthread_cond_signal (& condition_var) est appelé mais à qui il signale quand il n'y a pas de thread en attente (pthread_cond_wait n'est pas appelé)? –

0
#include "stdafx.h" 
#include "TestC.h" 
#include"afxmt.h " 

///////////////////////////////////////////////////////////////////////////// 
// The one and only application object 

CWinApp theApp; 

using namespace std; 

CEvent myEvent1; 
CEvent myEvent2; 

UINT PrintEven(LPVOID pParam) 
{ 
    int nNum = 2; 
    while(nNum < 20) 
    { 
     myEvent2.Lock(); 
     CString str; 
     str.Format("%d\n",nNum); 
     printf(str); 
     nNum += 2; 
     myEvent1.SetEvent(); 
    } 
    return 1; 
} 

UINT PrintOdd(LPVOID pParam) 
{ 
    int nNum = 1; 
    while(nNum < 20) 
    { 
     //myEvent1.Lock(); 
     CString str; 
     str.Format("%d\n",nNum); 
     printf(str); 
     nNum += 2; 
     myEvent2.SetEvent(); 
     myEvent1.Lock(); 
    } 
    return 1; 
} 
int _tmain(int argc, TCHAR* argv[], TCHAR* envp[]) 
{ 
    AfxBeginThread(PrintOdd, 0); 
    AfxBeginThread(PrintEven, 0); 
    Sleep(1000); 
    return 1; 
} 
+0

L'utilisateur a posé des questions sur l'utilisation de pthread spécifiquement, mais c'est aussi le type de question qui pourrait être mieux résolu par une description de * comment * pour résoudre le problème; pour quelqu'un qui apprend à faire cela, même en utilisant la bibliothèque que vous avez choisie, il est probable que plusieurs aspects de ce code ne seront pas clairs. – jimwise