program to print odd numbers and even numbers on seperate threads
I am learning 开发者_开发百科programming using pthreads. How can I write a program to print odd numbers and even numbers on separate threads.
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.
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 ...
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.
#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;
}
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.
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();
}
}
--------
精彩评论