如何在posix线程之间切换?

时间:2013-05-03 22:51:43

标签: c multithreading pthreads scheduler

以下是我要做的事情:

  1. 从主线程开始10个posix线程。
  2. 10个线程中的每个线程都会执行100次操作。
  3. 这是我需要帮助的。

    1. 我想允许thread_1做10秒的事情(当线程2-10被挂起)然后我想让线程2做它的事情,而线程1和线程3-10被挂起等等
    2. 我该怎么做?我正在查看一些pthread教程,但事情似乎很复杂,即使我想要做的事情非常简单。

3 个答案:

答案 0 :(得分:2)

除了讨论OP的问题是否有意义之外,可能的解决方案如下:

为每个要安排的线程安装信号处理程序。这个处理程序是在SIGUSR1上触发的,内部只是调用对pause()的调用。

线程函数都以调用pause()开始,该函数在创建后立即挂起所有线程。

使用pthread_create()创建所有线程作为计划。将创建的pthread存储到数组pthreads

将要运行的第一个pthread(从pthread)分配到pthread_first

开始调度调用pthread_kill(pthread_first, SIGUSR2)以恢复首先运行的线程(通过使pause()阻塞它来返回)。将pthread_current变为pthread_first

要实际执行调度,其他线程(可能是主线程)无限循环并调用sleep(SCHEDULING_INTERVALL)然后调用pthread_kill(pthread_current, SIGUSR1)来挂起当前线程(通过调用其信号处理程序并将其运行到{ {1}})。然后调用pause()以恢复下一个线程(通过使其pthread_kill(pthread_next, SIGUSR2)阻塞,返回)。将pause()变为pthreat_currentpthread_next成为线程创建期间填充的数组pthread_next中的另一个条目。

但请注意:

由于信号中断并由pthread暂停的线程可能已经在共享资源上做了一些工作并且保持它们直到恢复,因此踩到彼此的脚趾的可能性很高。

致所有其他人:是的,打败我; - )


<强>更新

等效示例:

pause()

预期产出:

#include <errno.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <pthread.h>
#include <signal.h>

#define THREADSMAX (3)
#define SCHEDULING_INTERVALL (5) /* seconds */

void
sigusr_handler(int signo)
{
  if (SIGUSR1 == signo)
    {
      pause();
    }
}

void *
thread_function(void * pv)
{
  intptr_t iThread = (intptr_t) pv;

  pause();

    {
      int i = 0;
      for (;;)
        {
          printf("%d: %d\n", (int) iThread, i++);
          sleep(1);
        }
    }

  pthread_exit(NULL);
}

int
main(int argc, char ** argv)
{
  struct sigaction signal_action;
  memset(&signal_action, 0, sizeof(signal_action));
  signal_action.sa_handler = sigusr_handler;
  sigemptyset(&signal_action.sa_mask);

  sigaction(SIGUSR1, &signal_action, NULL);
  sigaction(SIGUSR2, &signal_action, NULL);

    {
      pthread_t threads[THREADSMAX] =
        { 0 };

      intptr_t iThread = 0;

      /* create threads */
      for (; iThread < THREADSMAX; ++iThread)
        {
          int iResult = pthread_create(&threads[iThread], NULL, thread_function,
              (void *) iThread);
          if (iResult)
            {
              errno = iResult;
              perror("pthread_created()");
              exit(1);
            }
        }

      sleep(1); /* Unreliable workaround: Try to make sure all threads have started and block in "pause()". See comments on how this might be fixed nicely ... */

      /* scheduling loop */
      for (iThread = 0;; ++iThread)
        {
          if (THREADSMAX == iThread)
            {
              iThread = 0;
            }
            /* Resume current thread */
            {
              int iResult = pthread_kill(threads[iThread], SIGUSR2);
              if (iResult)
                {
                  errno = iResult;
                  perror("pthread_kill(..., SIGUSR2)");
                  exit(2);
                }
            }

          sleep(SCHEDULING_INTERVALL);

          /* Suspend current thread */
            {
              int iResult = pthread_kill(threads[iThread], SIGUSR1);
              if (iResult)
                {
                  errno = iResult;
                  perror("pthread_kill(..., SIGUSR1)");
                  exit(3);
                }
            }
        }
    }

  return 0;
}

答案 1 :(得分:1)

  1. POSIX Threads: Condition Variables - what's the point?
  2. Joining and Detaching Threadsenter image description here
  3. 使用sleep()和调度程序将上下文切换到另一个进程。 IMO它不是那么糟糕的解决方案 - 它不是通用的,因为在某些情况下100ms是很多时间而在另一种情况下它非常短。
  4. Implement by ourself condition variables or some sort of synchronizer - 但确实不推荐。

答案 2 :(得分:1)

您没有很好地说明您的要求。线程是否都在独立数据上运行(不需要它们之间的同步)?如果是这样,尝试以10秒为单位进行自己的课程安排的整个想法是没有意义的。让他们全都跑步并做他们的事。当然,实现你所要求的使用定时器信号并控制哪些线程阻塞了信号,这将是非常容易的,但它也将完全无用。

另一方面,如果你的线程之间确实存在数据依赖关系,那么“运行10秒然后将控制转移到另一个线程”的任何模式都是无效的;如果由于第一个线程保持锁定而导致下一个线程无法继续,则可能导致死锁。 (我想它并不完全是 dead -lock,因为控制最终将返回到第一个线程,但是如果涉及多个锁,延迟可能会在非常大的顺序上增长。)相反,在这种情况下,你的目标是让哪个线程运行受数据流控制。