【问题标题】:program to print odd numbers and even numbers on seperate threads在不同线程上打印奇数和偶数的程序
【发布时间】:2011-02-14 02:41:00
【问题描述】:

我正在学习使用 pthread 进行编程。 如何编写程序在不同的线程上打印奇数和偶数。

【问题讨论】:

  • 输出应该是1,2,3.....但是奇数和偶数应该打印在不同的线程上。
  • 除非你使用互斥体,否则你不能保证两个不同线程的输出会以什么顺序出现。
  • @QuantumPete - 互斥体不保证顺序。当线程 A 释放互斥锁时,不能保证线程 B 会在线程 A 再次请求之前被唤醒。
  • +1 - 对于任何自学如何使用 pthreads 的人来说都是一个有用的问题。

标签: c posix


【解决方案1】:

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

【讨论】:

    【解决方案2】:

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

    pthread_mutex_t count_mutex = PTHREAD_MUTEX_INITIALIZER; pthread_cond_t 条件变量 = PTHREAD_COND_INITIALIZER; 无效 *functionCount1(); 无效 *functionCount2(); 整数计数 = 0; #define COUNT_DONE 200 主要的() { pthread_t 线程1,线程2; pthread_create(&thread1, NULL, &functionCount1, NULL); pthread_create(&thread2, NULL, &functionCount2, NULL); pthread_join(thread1, NULL); pthread_join(thread2, NULL); 退出(0); } // 打印奇数 无效 *functionCount1() { 为了(;;) { // 锁定互斥量,然后等待信号释放互斥量 pthread_mutex_lock( &count_mutex ); // 检查最后发出的值是否为奇数;如果是,请等到 // 打印一个偶数 如果(计数 % 2 != 0){ pthread_cond_wait( &condition_var, &count_mutex ); } 计数++; printf("计数器值函数Count1: %d\n",count); pthread_cond_signal( &condition_var ); 如果(计数> = COUNT_DONE){ pthread_mutex_unlock( &count_mutex ); 返回(空); } pthread_mutex_unlock( &count_mutex ); } } // 打印偶数 无效 *functionCount2() { 为了(;;) { // 锁定互斥量,然后等待信号释放互斥量 pthread_mutex_lock( &count_mutex ); // 检查最后发出的值是否为偶数;如果是,请等到 // 打印一个奇数 如果(计数 % 2 == 0){ pthread_cond_wait( &condition_var, &count_mutex ); } 计数++; printf("计数器值函数Count2: %d\n",count); pthread_cond_signal( &condition_var ); 如果(计数> = COUNT_DONE){ pthread_mutex_unlock( &count_mutex ); 返回(空); } pthread_mutex_unlock( &count_mutex ); } } 输出:: ubuntu:~/work$ gcc even_odd.c -lpthread ubuntu:~/work$ ./a.out 计数器值函数Count1:1 计数器值函数Count2:2 计数器值函数Count1:3 计数器值函数Count2:4 计数器值函数Count1:5 计数器值函数Count2:6 计数器值函数Count1:7 计数器值函数Count2:8 计数器值函数Count1:9 计数器值函数Count2:10 ...

    【讨论】:

    • 我不是很明白,当count最初为0时,这个条件if(count%2 !=0)会失败并且没有调用pthread_cond_wait(&condition_var, &count_mutex);。稍后 count++ 增加并调用 pthread_cond_signal( &condition_var ),但是当没有等待线程时它向谁发出信号(不调用 pthread_cond_wait)?
    【解决方案3】:

    通过线程函数参数传递一个指示值来指示线程应该打印奇数还是偶数。

    根据相同,从 0(偶数)或 1(奇数)开始,并在线程和打印中保持递增 2。

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

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

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

    【讨论】:

    • 我正在学习 pthreads..我正在寻找的解决方案是使用信号量进行线程同步。输出应该是 1,2,3.....但是应该打印奇数和偶数单独的线程。如果有人可以提供使用细节,那将会很有帮助。还有任何研究 pthreads 的链接。
    【解决方案4】:
    #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;
    }
    

    【讨论】:

    • 用户询问了关于使用 pthread 的具体问题,但这也是此类问题,最好通过描述如何来解决问题;对于学习这样做的人,即使使用您选择的库,这段代码的几个方面也可能不清楚。
    【解决方案5】:

    从逻辑上讲,您可以使用带有变量(值)的标志( 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();
    
    }
    

    }

    输出如下。

    【讨论】:

      【解决方案6】:

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

      【讨论】:

      • [这被 SO 标记为“新用户提供的旧问题的最新答案。此评论是在该上下文中。] 问题是关于 pthreads。因此,Java 答案不是特别响应。请考虑删除它。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-08-26
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-05-17
      相关资源
      最近更新 更多