了解并行线程执行

ars*_*ars 5 c multithreading pthreads

编写简单的 C 代码,尝试控制两个不同线程的输出:

#include <pthread.h>
#include <semaphore.h>
#include <stdio.h>

sem_t sem;

void* thread_func(void* aArgs)
{
  printf("Entering thread %p with %d\n", (void*)pthread_self(), (int)aArgs);
  int i = 0;
  for(;i < 10; i++)
  {
    sem_wait(&sem);
    if ((i % 2) == (int)aArgs)
      printf("val is %d in thread %p \n", i, (void*)pthread_self());
    sem_post(&sem);
  }
}

int main()
{
  pthread_t thread_1, thread_2;

  sem_init(&sem, 0, 1);

  pthread_create(&thread_1, NULL, (void*)thread_func, (void*)0);
  pthread_create(&thread_2, NULL, (void*)thread_func, (void*)1);

  pthread_join(thread_1, NULL);
  pthread_join(thread_2, NULL);

  sem_destroy(&sem);

  return 0;
}
Run Code Online (Sandbox Code Playgroud)

我想要实现的是混合奇数和偶数的序列。但我从一个线程接收所有数字,然后从第二个线程接收所有其他数字,如下所示(即使我增加循环计数器幅度):

Entering thread 0xb75f2b40 with 0
val is 0 in thread 0xb75f2b40 
val is 2 in thread 0xb75f2b40 
val is 4 in thread 0xb75f2b40 
val is 6 in thread 0xb75f2b40 
val is 8 in thread 0xb75f2b40 
Entering thread 0xb6df1b40 with 1
val is 1 in thread 0xb6df1b40 
val is 3 in thread 0xb6df1b40 
val is 5 in thread 0xb6df1b40 
val is 7 in thread 0xb6df1b40 
val is 9 in thread 0xb6df1b40
Run Code Online (Sandbox Code Playgroud)

问题是为什么两个独立线程的行为就像两个连续任务一样?为什么第二个线程在第一个线程尚未完成所有工作之前才获得执行控制权?

我尝试将 pthread_yield() 添加到 for 循环的末尾,但情况并没有显着改变:有时我得到预期的输出,有时 - 如上所述。

UPD。如何实现确定性的一对一线程执行?是否有任何同步原语?

JS1*_*JS1 4

如果您想获得所需的输出,您应该使用两个信号量而不是一个。每个线程都应该等待自己的信号量,并在每次循环迭代完成后发布另一个线程的信号量。主线程可以创建一个值为 1 的信号量,另一个值为 0 的信号量,以便正确启动。这将强制两个线程以交替顺序运行。

由于当前编写的程序,执行 asem_post后跟 asem_wait可能会导致同一线程立即获取信号量(在单 CPU 系统上)。我很惊讶这pthread_yield没有帮助,但无论如何使用两个信号量都将保证正确的排序。