5

I am learning programming using pthreads. How can I write a program to print odd numbers and even numbers on separate threads.

user329013
  • 111
  • 2
  • 2
  • 3
  • The output should be 1,2,3.....But odd numbers and even numbers should be printed on seperate threads. – user329013 Apr 30 '10 at 05:44
  • You can't guarantee in what order the output from two different threads will appear unless you use a mutex. – Peter Kühne Apr 30 '10 at 05:56
  • @QuantumPete - a mutex does not guarantee order. When thread A releases the mutex, there is no guarantee thread B will be woken up before thread A asks for it again. – R Samuel Klatchko Apr 30 '10 at 05:58
  • 2
    +1 - Useful question for anyone who is teaching themselves how to work with pthreads. – Tim Post May 23 '10 at 09:46

6 Answers6

9

You need two synchronization objects such as a semaphore or a condition variable. The idea is that thread A requests semaphore A before it prints and releases semaphore B after while thread B does the opposite.

The idea is that after thread A requests semaphore A, it will drop the semaphore to 0. The next time it requests semaphore A it will block until thread B releases the semaphore.

In pseudo code, this looks like:

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)

Since you want to teach yourself threads programming, I'll leave it to you to convert this into actual pthreads code.

R Samuel Klatchko
  • 74,869
  • 16
  • 134
  • 187
3

I think using a conditional variable and a mutex could solve this problem.


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

Vishal K
  • 1,164
  • 1
  • 10
  • 21
  • I didn't really understand it, when count initially is 0, this condition if(count%2 !=0) would fail and there is no call to pthread_cond_wait( &condition_var, &count_mutex );. Later on count++ is incremented and pthread_cond_signal( &condition_var ) is called but whom it is signaling to when there is no waiting thread (pthread_cond_wait is not called) ? – Amit Singh Tomar Aug 02 '16 at 13:29
1

Pass an indicator value to indicate if the thread should be printing odd number or even number through the thread function argument.

Depending upon the same, start from 0 (for even numbers) or 1 (for odd numbers) and keep incrementing by 2 in both the threads and print.

You can also print the thread-id along with the number to indicate which thread is printing what.

I assume you know how to use pthreads.

[Update]: Link for pthreads Even with the use of semaphores or mutex, it is difficult for you to get the output in order of 1,2,3 etc as you never know which thread will get the chance to execute first. For this, you may have to use some advanced concepts like thread priority or Inter-thread communication using conditional variables. These are just hints. I hope if you go through the link you will get more information.

Jay
  • 24,173
  • 25
  • 93
  • 141
  • I am learning pthreads..The solution i was looking for was thread synchronization using semaphores.The output should be 1,2,3.....But odd numbers and even numbers should be printed on separate threads.It would be helpful if anyone can provide the details of usage. Also any link to study pthreads. – user329013 Apr 30 '10 at 05:53
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;
}
  • The user had asked about using pthread specifically, but this is also the type of question which might be better answered by a description of *how* to solve the problem; for someone learning to do this, even using the library you've chosen, it is likely that several aspects of this code will not be clear. – jimwise Jan 24 '13 at 18:58
-1

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

-------- 
user229044
  • 232,980
  • 40
  • 330
  • 338
  • [This was flagged by SO as a "late answer to an old question, provided by a new user. This comment is in that context.] The question is about pthreads. As such, a Java answer is not particularly responsive. Please consider deleting it. – danfuzz Dec 05 '12 at 18:52
-1

Logically, you can control using a flag ( printOdd ) with a variable (value) constantly incremented on printing each time.

Using lambda's in 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();

}

}

The output is as follows.

enter image description here

jegadeesh
  • 109
  • 2
  • 8