программа для печати нечетных и четных чисел в отдельных потоках - PullRequest
5 голосов
/ 30 апреля 2010

Я учусь программированию с использованием pthreads. Как мне написать программу для печати нечетных и четных чисел в отдельных потоках.

Ответы [ 6 ]

8 голосов
/ 30 апреля 2010

Вам нужны два объекта синхронизации, такие как семафор или переменная условия. Идея состоит в том, что поток A запрашивает семафор A перед тем, как печатать и выпускать семафор B после того, как поток B делает обратное.

Идея состоит в том, что после того, как поток A запросит семафор A, он сбросит семафор до 0. В следующий раз, когда он запросит семафор A, он заблокируется, пока поток B не освободит семафор.

В псевдокоде это выглядит так:

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)

Поскольку вы хотите научиться программировать потоки, я оставлю вам возможность преобразовать это в реальный код pthreads.

3 голосов
/ 26 апреля 2012

Я думаю, что использование условной переменной и мьютекса может решить эту проблему.


    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
    ...

1 голос
/ 30 апреля 2010

Передайте значение индикатора, чтобы указать, должен ли поток печатать нечетное число или четное число через аргумент функции потока.

В зависимости от того же, начните с 0 (для четных чисел) или 1 (для нечетных чисел) и продолжайте увеличивать на 2 как в потоках, так и в печати. ​​

Вы также можете распечатать идентификатор потока вместе с номером, чтобы указать, какая нить печатает что.

Полагаю, вы знаете, как использовать pthreads.

[Обновление]: ссылка для pthreads Даже при использовании семафоров или мьютексов вам будет сложно получить выходные данные порядка 1,2,3 и т. Д., Так как вы никогда не знаете, какой поток получит шанс выполнить первым. Для этого вам, возможно, придется использовать некоторые расширенные понятия, такие как приоритет потока или межпотоковое взаимодействие с использованием условных переменных. Это всего лишь подсказки. Я надеюсь, что если вы перейдете по ссылке, вы получите больше информации.

0 голосов
/ 03 мая 2019

Логически вы можете управлять с помощью флага (printOdd) с переменной (значением), постоянно увеличивающейся при печати каждый раз.

Использование лямбды в java 8,

public class OddEvenThreads {

final int limit = 20; // constant
static volatile int value = 1;
static volatile boolean printOdd = true;

public static void main(String[] args) {

    new Thread(() -> {
        while (value < limit) {
            if (!printOdd && (value % 2) == 0) {
                System.out.println("Even Thread :  " + value++);
                printOdd = !printOdd;
            }
        }
    }).start();

    new Thread(() -> {
        while (value < limit) {
            if (printOdd && (value % 2) != 0) {
                System.out.println("Odd Thread :  " + value++);
                printOdd = !printOdd;
            }
        }
    }).start();

}

}

Вывод следующий.

enter image description here

0 голосов
/ 24 января 2013
#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 голосов
/ 03 декабря 2010

В 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();
}
}

-------- 
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...