如何使用从特定线程到 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;
}
很清楚我的需求。
我有一个“管理器”线程需要管理一种具有 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;
}