这是我正在尝试做的事情:
- 从主线程启动 10 个 posix 线程。
- 10 个线程中的每一个都会执行一些操作,比如 100 次。
这是我需要帮助的。
- 我想允许 thread_1 做它的事情 10 秒(同时线程 2-10 被挂起),然后我想允许线程 2 在线程 1 和线程 3-10 被挂起时做它的事情,依此类推。
我该怎么做?我在看一些 pthread 教程,但事情似乎很复杂,尽管我想做的事情很简单。
这是我正在尝试做的事情:
这是我需要帮助的。
我该怎么做?我在看一些 pthread 教程,但事情似乎很复杂,尽管我想做的事情很简单。
除了关于 OP 的问题是否有意义的任何讨论之外,可能的解决方案可能如下:
为每个要调度的线程安装一个信号处理程序。这个处理程序在 say 上被触发,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)
以挂起当前线程(通过调用其信号处理程序并运行到pause()
)。然后调用pthread_kill(pthread_next, SIGUSR2)
以恢复下一个线程(通过pause()
使其阻塞返回)。Make pthreat_current
become pthread_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;
}
预期输出:
0: 0
0: 1
0: 2
0: 3
0: 4
1: 0
1: 1
1: 2
1: 3
1: 4
2: 0
2: 1
2: 2
2: 3
2: 4
0: 5
0: 6
0: 7
0: 8
0: 9
1: 5
1: 6
1: 7
1: 8
1: 9
2: 5
2: 6
...
sleep()
和调度程序将上下文切换到另一个进程。IMO 它不是那么糟糕的解决方案 - 它不是通用的,因为在某些情况下 100 毫秒是很多时间,而在另一种情况下它非常短。 您没有很好地说明您的要求。线程是否都对独立数据进行操作(它们之间不需要同步)?如果是这样,尝试以 10 秒为单位进行自己的课程安排的整个想法是荒谬的。让他们都跑,做他们的事。当然,使用计时器信号并控制哪些线程阻塞了信号会很容易实现您的要求,但它也完全没用。
另一方面,如果您的线程之间确实存在数据依赖关系,那么“运行 10 秒然后将控制权转移到另一个线程”的任何模式都是无效的;如果下一个线程由于第一个线程持有的锁而无法继续进行,则可能导致死锁。(我想它并不完全是死锁,因为控制最终会返回到第一个线程,但是如果涉及多个锁,延迟可能会以非常大的顺序增长。)相反,在这种情况下,您应该瞄准线程运行受数据流控制。