如何在线程之间进行通信

6

我如何在C++中创建线程并在主线程和另一个线程之间进行通信?

一些代码示例将会很有帮助。


10
有一本由Anthony Williams所著的书叫做"C++ Concurrency in Action"。它讨论了在C++中使用线程编程,包括一些示例。除非您将问题具体化,否则我建议您阅读这本书。 - Dietmar Kühl
这取决于您需要的通信类型。主要可以使用共享状态(一组使用同步技术访问的变量)或消息传递(使用管道、套接字等)。您打算使用这些线程做什么? - bruno nery
4个回答

2

线程与其作用域共享变量,因此互斥锁非常重要。

因此,您可以通过编辑两个线程共同使用的变量来轻松进行通信:

#include <iostream>
#include <pthread.h> 
main()  {
    pthread_t f2_thread, f1_thread; 
    void *f2(), *f1();
    int i1;
    i1 = 1;
    pthread_create(&f1_thread,NULL,f1,&i1);
    pthread_create(&f2_thread,NULL,f2,&i1);
    pthread_join(f1_thread,NULL);
    pthread_join(f2_thread,NULL);
}
void *f1(int *x){
  std::cout << *x << std::endl;
}
void *f2(int *x){
  sleep(1)
  std::cout << ++(*x) << std::endl;
}

这应该会打印出以下内容:
1
2

变量i1已在线程之间共享。这是一种通信形式,可以共享类、结构体、字符串或任何你想要的内容。

注意:这段代码几乎肯定会导致线程竞争。这只是一个示例,当在线程之间共享内存时,应始终使用同步和线程安全的做法。


@DietmarKühl p_threads可以在C++中使用,我认为这只是关于线程的问题。 - Fantastic Mr Fox
@DietmarKühl 好的,我道歉了。但是可移植线程的概念是相同的,您仍然可以使用公共变量。 - Fantastic Mr Fox
1
是的,确实如此。但不是你使用它们的方式!如果没有同步,你无法使用变量进行通信,即使是任何内置类型!你所创建的是一个不错的、简单的数据竞争示例。 - Dietmar Kühl
@DietmarKühl,这就是为什么我在回答开始处提到了互斥锁。OP只是想要一个线程间通信的例子,我相信我已经提供了。 - Fantastic Mr Fox
1
@JohannesSchaub-litb 1. 我建议使用互斥锁,这段代码只是一个非常简单的示例,展示了如何在两个线程中使用整数。2. OP并没有要求可移植性或某些特定的代码来完成某些任务,他只是要求一个线程间通信的示例。我提供了一个简单的示例来演示其中一种方法。我从未表示过它是可移植或有用的,它只是一个示例而已。 - Fantastic Mr Fox
显示剩余4条评论

1
在创建线程时,答案很明显(我认为是这样的),如果你使用C++11,那么使用std::thread,否则使用boost::thread。但是,在消息传递的情况下,它取决于你的问题和编程风格。
作为一种通用解决方案,我更喜欢使用boost::asio::io_service,它非常灵活,可以发布任何类型的函数或函数对象以在其他线程的上下文中执行。使用这种技术,您不需要任何互斥锁等,还可以将线程分组到消费者和生产者,并提供许多其他有用的功能。

0

好的,我会告诉你我知道的最简单的: _beginthread

  • 为了让它起作用,你必须包含process.h
  • 必须有一个要线程化的函数。
  • 函数的输入参数必须是(void *)。
  • 当需要结束时,函数应该有一个_endthread()

在下面的程序中,两个线程竞争查找pi值。如果其中一个找到了pi值,它就会通知另一个线程应该结束。在main()中还打印了哪个线程找到了pi。第三个线程只是等待其他线程之一完成。

      #include<process.h>
      #include<windows.h> //for the Sleep()
      #include<stdio.h>
      volatile boolean found=false;
      volatile int who=0;

      void find_pi_core1(void * iterations)
      {

          int * ite=(int *)iterations;
          for(int i=0;i<ite;i++)
          {
              //a sample of Monte-Carlo method here to find pi 
              //gets pi with more precision with additional iterations
               if(found) _endthread();
          }
          found=true;who=1;
          _endthread();    

       }

       void find_pi_core2(void * iterations)
       {

           int * ite=(int *)iterations;
           for(int i=0;i<ite;i++)
           {
                //a sample of Monte-Carlo method here to find pi 
                //gets pi with more precision with additional iterations
                 if(found) _endthread();
           }
           found=true;who=2;
          _endthread();
      }

       void printscreeN(void * dummy)
       {

          while(!found)
          {
              Sleep(30);      //if dont sleep, it gets a lot of cpu power
          }
          printf(" found! \n" );
          _endthread();
      }

      int main()
      {

                      Function name
                          ^       Stack size
                          |          ^           Function parameter
                          |          |             ^
          _beginthread(find_pi_core1,0,(void *) 3000000);
          _beginthread(find_pi_core2,0,(void *) 2500000);
          _beginthread(printscreeN,0,(void *)0);
          Sleep(3000);
          if(found)
          { 
               printf("pi has been found! core-%d has found pi first ",who);
          }
          else
          {printf("pi has not been bound!");}
          return 0;
      }

-2

线程创建是依赖于操作系统的。

在Linux上,可以使用pthread库函数pthread_create来创建线程,并使用pthread_join等待线程完成。

在Windows上,可以使用CreateThread() Windows API函数来创建线程,并使用WaitForSingleObject()函数等待线程完成。


1
你可以在两者上都使用std::threadboost::thread - juanchopanza
4
当前的C++标准(ISO/IEC 14882:2011)规定了线程创建和线程通信原语,也就是说,它完全不依赖于操作系统。 - Dietmar Kühl

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接