线程如何在C中工作?

时间:2015-11-05 14:14:43

标签: c multithreading pthreads posix

如何重现输出:

#include <pthread.h>
#include <stdlib.h>
#include <unistd.h>
#include <stdio.h>

int myglobal;

void *thread_function(void *arg) {
  int i,j;
  for ( i=0; i<20; i++ ) {
    j=myglobal;
    j=j+1;
    printf(".");
    fflush(stdout);
    sleep(1);
    myglobal=j;
  }
  return NULL;
}

int main(void) {
  pthread_t mythread;
  int i;

  myglobal = 0;

  if ( pthread_create( &mythread, NULL, thread_function, NULL) ) {
    printf("error creating thread.");
    abort();
  }

  for ( i=0; i<20; i++) {
    myglobal=myglobal+1;
    printf("o");
    fflush(stdout);
    sleep(1);
  }

  if ( pthread_join ( mythread, NULL ) ) {
    printf("error joining thread.");
    abort();
  }

  printf("\nmyglobal equals %d\n",myglobal);
  exit(0);
}

输出:

o..oo..oo..oo..oo..oo..oo..oo..oo..oo..o

myglobal equals21

问题:

有人可以解释如何生成此输出吗? 为什么他们不像“o.o.o.o”那样互相交替?

4 个答案:

答案 0 :(得分:4)

在您的示例中,有两个线程同时运行。两者都在ABOUT同时开始打印,两者都在打印之间等待大约1秒。您无法准确确定“。”的顺序。 vs“o”,只是随着时间的推移,每个人的数量大致相同。

如果,你加了半秒睡眠:

ProtocolA
然后,两个线程将更加一致地交替其时间,并且您将获得预期的序列。但请注意,即便如此,在很长一段时间内,两个线程的时间不同步,并且它们可以漂移(并且弄乱了“o.o.o.o.o”的完美一致性)

答案 1 :(得分:3)

  

有人可以解释如何生成此输出吗?为什么他们不像“o.o.o.o”那样互相交替?

它们不能可靠地交替,因为您没有提供任何机制来使它们这样做。特别是,使用sleep()函数无法实现该目标。这不是一个线程“超越”另一个线程的问题。相反,在每次迭代时,两个线程都有资格在几乎完全相同的时间运行,并且机器似乎倾向于让最后运行的线程首先恢复。这是允许的,但不是必需的。

依靠时间来同步线程活动是不安全的。您需要使用IPC(管道,信号)或线程同步对象,如信号量,互斥量或条件变量。

答案 2 :(得分:1)

每一秒,你的两个线程都被唤醒并尝试打印它们各自的char,但你不能对它们再次运行的顺序做出任何假设,看来在你的情况下你有:<top>t1 then t2<top>t2 then t1<top>t1 then t2<top>...给你o..oo..o等。

在我的系统(OSX El Capitan)上,调度给了我:o.o.o.o.

在我的Solaris上,它提供:o..oo..oo.o.o..oo..oo.o.o..oo.o..oo..oo.

在我的ubuntu上:o.o..o.o.oo..o.oo.o.o.o.o.o.o.o.o.o.o.o.

答案 3 :(得分:0)

创建线程时,它会从创建它的线程继承其优先级。您还可以使用setPriority方法在创建线程后随时修改线程的优先级。在任何给定时间,当准备好执行多个线程时,运行时系统选择执行具有最高优先级的Runnable线程。只有当该线程停止,产生或变为Not Runnable时,优先级较低的线程才会开始执行。如果两个具有相同优先级的线程正在等待CPU,则调度程序会任意选择其中一个运行。选定的线程将运行,直到满足下列条件之一:

  • 优先级较高的线程可以运行。
  • 它会产生,或者它的运行方法退出。
  • 在支持时间切片的系统上,其时间分配已过期。

然后第二个线程有机会运行,依此类推,直到解释器退出。