如何使用从特定线程到 play/pause 很多其他线程的信号量?

How to use a semaphore from a specific thread to play/pause a lot of other threads?

很清楚我的需求。

我有一个“管理器”线程需要管理一种具有 ON/OFF 值的“信号”。

当此 Manager 设置 Signal = ON 时,我希望代码中 运行 和暂停(可能是 WAIT(SIGNAL))的许多线程能够继续执行,直到“Manager”线程再次将 Signal = OFF。

这个“信号”是信号量吗?什么类型的信号量?我需要如何初始化它以及在哪里?

提前致谢!

正如我在评论中所说,线程控制很棘手。 C 级同步原语 - 就像 C 中的所有东西一样 - 低级。您需要从那里建立管理。

这是一种方法的粗略草图,每个 运行 线程使用一个互斥锁和一个 signal/wait 变量。

生产应用程序中您想要的许多东西在这里都缺失了:重用线程 table 条目、资源清理、正确等待最终终止等。但这是一个起点。

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

typedef enum { RUNNING, WAITING, KILLED } STATE;

typedef struct {
  int id;
  STATE state;
  pthread_t thread[1];
  pthread_mutex_t mutex[1];
  pthread_cond_t cond[1];
} CONTROLLED_THREAD;

void* poll_for_work(void *env) {
  CONTROLLED_THREAD *ct = env;
  while (1) {
    pthread_mutex_lock(ct->mutex);
    if (ct->state == KILLED) break;
    if (ct->state == WAITING) pthread_cond_wait(ct->cond, ct->mutex);
    pthread_mutex_unlock(ct->mutex);
    
    printf("Thread %d is working!\n", ct->id);
    sleep(3);
  }
  pthread_mutex_unlock(ct->mutex);
  return NULL;
}

void make_thread(CONTROLLED_THREAD *ct, int id) {
  ct->id = id;
  ct->state = RUNNING;
  pthread_mutex_init(ct->mutex, NULL);
  pthread_cond_init(ct->cond, NULL);
  pthread_create(ct->thread, NULL, poll_for_work, ct);
}

void kill_thread(CONTROLLED_THREAD *ct) {
  pthread_mutex_lock(ct->mutex);
  ct->state = KILLED;
  pthread_mutex_unlock(ct->mutex);
}

void pause_thread(CONTROLLED_THREAD *ct) {
  pthread_mutex_lock(ct->mutex);
  if (ct->state == RUNNING) ct->state = WAITING;
  pthread_mutex_unlock(ct->mutex);
}

void run_thread(CONTROLLED_THREAD *ct) {
  pthread_mutex_lock(ct->mutex);
  if (ct->state == WAITING) {
     ct->state = RUNNING;
     pthread_cond_signal(ct->cond);
  }
  pthread_mutex_unlock(ct->mutex);
}

int main(void) {
  char *buf = malloc(100);
  size_t len;
  int n = 0, current_id = 0, id;
  CONTROLLED_THREAD threads[100];

  while (1) {
    getline(&buf, &len, stdin);
    if (strncmp(buf, "new", 3) == 0) {
      make_thread(threads + n++, ++current_id);
    } else if (strncmp(buf, "kill", 4) == 0 && sscanf(buf + 4, "%d", &id) == 1) {
      for (int i = 0; i < n; ++i) {
        if (threads[i].id == id) {
          kill_thread(threads + i);
          break;
        }
      }
    } else if (strncmp(buf, "pause", 5) == 0) {
      for (int i = 0; i < n; ++i) pause_thread(threads + i);
    } else if (strncmp(buf, "run", 3) == 0) {
      for (int i = 0; i < n; ++i) run_thread(threads + i);
    } else {
      printf("unknown command %s\n", buf);
    }
  }
  free(buf);
  return 0;
}