程序在不同的线程上打印奇数和偶数

时间:2010-04-30 05:41:53

标签: c posix

我正在学习使用pthreads编程。 如何编写程序在单独的线程上打印奇数和偶数。

6 个答案:

答案 0 :(得分:8)

您需要两个同步对象,例如信号量或条件变量。这个想法是线程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代码。

答案 1 :(得分:3)

我认为使用条件变量和互斥量可以解决这个问题。


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

答案 2 :(得分:1)

传递一个指示器值,指示线程是否应该通过线程函数参数打印奇数或偶数。

根据相同的不同,从0(对于偶数)或1(对于奇数)开始,并在两个线程和打印中继续递增2.

您还可以打印线程ID以及数字,以指示哪个线程正在打印什么。

我假设你知道如何使用pthreads。

[更新]:pthreads的链接           即使使用信号量或互斥量,您也很难按1,2,3等顺序获取输出,因为您永远不知道哪个线程有机会先执行。为此,您可能必须使用一些高级概念,如线程优先级或使用条件变量的线程间通信。这些只是提示。我希望你通过链接获得更多信息。

答案 3 :(得分: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;
}

答案 4 :(得分:0)

从逻辑上讲,您可以使用标记(printOdd)进行控制,该标记的变量(值)每次打印时都会不断增加。

在Java 8中使用lambda,

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

答案 5 :(得分:-1)

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

--------