在不使用条件变量或其他各种同步原语的情况下暂停线程执行

Pause thread execution without using condition variable or other various synchronization pritmives

问题

我希望能够暂停来自不同线程的线程的执行。注意暂停的线程不应该合作。目标线程的暂停不必在暂停线程想要暂停时立即发生。允许延迟暂停。

我似乎找不到这方面的任何信息,因为所有搜索都为我提供了使用条件变量的结果...

想法

OS-不可知论是可取的,但不是必需的。这可能非常 OS 依赖,因为打乱调度和线程是一个非常低级的操作。

在 Unix-like OS 上,有 pthread_kill() 将信号传送到指定的线程。您可以安排该信号有一个处理程序,该处理程序等待直到以某种方式被告知才能恢复。

这是一个简单的例子,“暂停”只是在恢复之前休眠一段固定的时间。 Try on godbolt.

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

void safe_print(const char *s) {
    int saved_errno = errno;
    if (write(1, s, strlen(s)) < 0) {
        exit(1);
    }
    errno = saved_errno;
}

void sleep_msec(int msec) {
    struct timespec t = {
                         .tv_sec = msec / 1000,
                         .tv_nsec = (msec % 1000) * 1000 * 1000
    };
    nanosleep(&t, NULL);
}

void *work(void *unused) {
    (void) unused;

    for (;;) {
        safe_print("I am running!\n");
        sleep_msec(100);
    }
    return NULL;
}

void handler(int sig) {
    (void) sig;
    safe_print("I am stopped.\n");
    sleep_msec(500);
}

int main(void) {

    pthread_t thr;
    pthread_create(&thr, NULL, work, NULL);

    sigset_t empty;
    sigemptyset(&empty);
    struct sigaction sa = {
                           .sa_handler = handler,
                           .sa_flags = 0,
    };
    sigemptyset(&sa.sa_mask);
    sigaction(SIGUSR1, &sa, NULL);

    for (int i = 0; i < 5; i++) {
        sleep_msec(1000);
        pthread_kill(thr, SIGUSR1);
    }
    pthread_cancel(thr);
    pthread_join(thr, NULL);
    return 0;
}