如何将数据传递给正在运行的线程

mon*_*ing 9 c c++ multithreading pthreads

使用pthread时,我可以在创建线程时传递数据.

将新数据传递给已经运行的线程的正确方法是什么?

我正在考虑制作一个全局变量并从中读取我的线程.

谢谢

Cha*_*tin 6

这肯定会奏效.基本上,线程只是共享相同内存空间的轻量级进程.存在于该存储空间中的全局变量可供每个线程使用.

伎俩不是读者和作家一样.如果你有一个简单的全局内存块,比如a int,则分配给它int可能是安全的.Bt考虑一些更复杂的东西,比如a struct.只是要明确,让我们说我们有

struct S { int a; float b; } s1, s2;
Run Code Online (Sandbox Code Playgroud)

现在s1,s2是类型的变量struct S.我们可以初始化它们

s1 = { 42,  3.14f };
Run Code Online (Sandbox Code Playgroud)

我们可以分配它们

s2 = s1;
Run Code Online (Sandbox Code Playgroud)

但是当我们分配它们时,处理器不能保证在一个步骤中完成对整个结构的赋值 - 我们说它不是原子的.现在让我们想象两个主题:

thread 1:
   while (true){
      printf("{%d,%f}\n", s2.a, s2.b );
      sleep(1);
   }

thread 2:
   while(true){
      sleep(1);
      s2 = s1;
      s1.a += 1;
      s1.b += 3.14f ;
   }
Run Code Online (Sandbox Code Playgroud)

我们可以看到我们期望s2拥有价值{42, 3.14}, {43, 6.28}, {44, 9.42}......

但我们看到的印刷品可能就是这样

 {42,3.14}
 {43,3.14}
 {43,6.28}
Run Code Online (Sandbox Code Playgroud)

要么

 {43,3.14}
 {44,6.28}
Run Code Online (Sandbox Code Playgroud)

等等.问题是线程1可以在该分配期间的任何时间获得控制并"查看"s2.

道德观点是,虽然全局记忆是完全可行的方法,但你需要考虑你的线程相互交叉的可能性.有几种解决方案,基本的一种是使用信号量.信号量有两个操作,容易混淆的命名来自荷兰的PV.

P只是等待变量为0并继续,向变量加1; V从变量中减去1.唯一特别的是他们原子地做到这一点- 他们不能被打断.

现在,你编码为

thread 1:
   while (true){
      P();
      printf("{%d,%f}\n", s2.a, s2.b );
      V();
      sleep(1);
   }

thread 2:
   while(true){
      sleep(1);
      P();
      s2 = s1;
      V();
      s1.a += 1;
      s1.b += 3.14f ;
   }
Run Code Online (Sandbox Code Playgroud)

并且你保证在线程1尝试打印时你永远不会让线程2半完成一项任务.

(顺便说一句,Pthreads有信号量.)

  • @Charlie:对不起,但我完全不同意线程的措辞是"轻量级进程".在许多操作系统中 - 包括许多unixoid系统(例如BSD)和Windows - 线程是*运行*代码的实体,而进程仅仅是线程,内存空间等的容器.现在,我意识到这可能是挑剔,但我认为区别非常重要且非常重要. (3认同)
  • @SAD从历史和事实两方面来看,这也是错误的.进程是具有一个 - 或具有线程,多个 - 程序计数器的内存空间.线程是"控制线程",包括程序计数器和堆栈.参见例如关于线程的Wiki文章.http://en.wikipedia.org/wiki/Thread_(computer_science)人们现在感到困惑,但一本好的操作系统书籍将讨论历史并清理它. (2认同)