SpringBoot2+Vue3+MyBatis-Plus馆藏管理系统全栈开发实践
2026/10/11 6:40:09
/* ============================================================ * sm_demo.c * 模拟 st_sm_deinit 的三种场景 * * 编译: gcc sm_demo.c -o sm_demo -lpthread * 运行: * ./sm_demo 1 worker 已经自己退出,deinit 直接收尾 * ./sm_demo 2 worker 优雅退出,deinit 等到后 join * ./sm_demo 3 worker 退不出,deinit 超时后 detach * ============================================================ */ #include <stdio.h> #include <stdlib.h> #include <string.h> #include <pthread.h> #include <unistd.h> #include <errno.h> /* ---------------- 可调参数 ---------------- */ #define SM_DEINIT_WAIT_MS 1000 /* deinit 最多等 1 秒 */ #define SM_DEINIT_SLICE_MS 10 /* 每 10ms 查一次 */ /* ---------------- 全局状态机 ---------------- */ typedef struct { pthread_mutex_t lock; pthread_t worker; int worker_alive; int abort_req; int mode; /* 1/2/3,决定 worker 行为 */ } sm_t; static sm_t g_sm; /* ---------------- worker 线程 ---------------- */ static void *worker_thread(void *arg) { (void)arg; printf("[worker] start, mode=%d\n", g_sm.mode); pthread_mutex_lock(&g_sm.lock); g_sm.worker_alive = 1; pthread_mutex_unlock(&g_sm.lock); if (g_sm.mode == 1) { /* 场景 1:worker 干完活自己退出,不等 abort */ printf("[worker] mode 1: work 300ms then exit by itself\n"); usleep(300 * 1000); } else if (g_sm.mode == 2) { /* 场景 2:worker 检查 abort,收到就退 */ printf("[worker] mode 2: wait for abort\n"); while (1) { pthread_mutex_lock(&g_sm.lock); int stop = g_sm.abort_req; pthread_mutex_unlock(&g_sm.lock); if (stop) break; usleep(10 * 1000); } printf("[worker] mode 2: got abort, exit\n"); } else { /* 场景 3:worker 忽略 abort,永远不退 */ printf("[worker] mode 3: ignore abort, never exit\n"); while (1) { usleep(10 * 1000); } } pthread_mutex_lock(&g_sm.lock); g_sm.worker_alive = 0; pthread_mutex_unlock(&g_sm.lock); printf("[worker] exit\n"); return NULL; } /* ---------------- 初始化 ---------------- */ static int sm_init(int mode) { memset(&g_sm, 0, sizeof(g_sm)); g_sm.mode = mode; pthread_mutex_init(&g_sm.lock, NULL); if (pthread_create(&g_sm.worker, NULL, worker_thread, NULL) != 0) { perror("pthread_create"); return -1; } printf("[init] worker created\n"); return 0; } /* ============================================================ * sm_deinit —— 完全照搬 st_sm_deinit 的结构 * ============================================================ */ static void sm_deinit(void) { int i = 0; int alive = 0; pthread_t th = 0; /* 第 1 段:设 abort_req,读出状态 */ pthread_mutex_lock(&g_sm.lock); g_sm.abort_req = 1; alive = g_sm.worker_alive; th = g_sm.worker; pthread_mutex_unlock(&g_sm.lock); printf("[deinit] alive=%d, th=%lu\n", alive, (unsigned long)th); /* 第 2 段:worker 已死,直接收尾 */ if (!alive) { if (th) { (void)pthread_join(th, NULL); pthread_mutex_lock(&g_sm.lock); g_sm.worker = 0; pthread_mutex_unlock(&g_sm.lock); printf("[deinit] joined dead worker\n"); } pthread_mutex_destroy(&g_sm.lock); printf("[deinit] path 2: worker already dead, done\n"); return; } /* 第 3 段:轮询等待 */ printf("[deinit] waiting for worker (max %d ms)...\n", SM_DEINIT_WAIT_MS); for (i = 0; i < SM_DEINIT_WAIT_MS / SM_DEINIT_SLICE_MS; i++) { pthread_mutex_lock(&g_sm.lock); alive = g_sm.worker_alive; pthread_mutex_unlock(&g_sm.lock); if (!alive) break; usleep(SM_DEINIT_SLICE_MS * 1000u); } /* 第 4 段:等到了,join + 销毁锁 */ pthread_mutex_lock(&g_sm.lock); if (!g_sm.worker_alive && g_sm.worker) { th = g_sm.worker; g_sm.worker = 0; pthread_mutex_unlock(&g_sm.lock); (void)pthread_join(th, NULL); pthread_mutex_destroy(&g_sm.lock); printf("[deinit] path 4: worker exited gracefully, done\n"); return; } /* 第 5 段:没等到,detach 兜底 */ if (g_sm.worker) { (void)pthread_detach(g_sm.worker); g_sm.worker = 0; g_sm.worker_alive = 0; } pthread_mutex_unlock(&g_sm.lock); printf("[deinit] path 5: worker still busy, detached for process exit\n"); } /* ---------------- main ---------------- */ int main(int argc, char *argv[]) { if (argc < 2) { printf("usage: %s <1|2|3>\n", argv[0]); printf(" 1: worker exits by itself before deinit\n"); printf(" 2: worker exits gracefully on abort\n"); printf(" 3: worker never exits, deinit detaches\n"); return 1; } int mode = atoi(argv[1]); if (mode < 1 || mode > 3) { printf("mode must be 1/2/3\n"); return 1; } printf("==== mode %d ====\n", mode); if (sm_init(mode) != 0) return 1; /* 不同场景,等待时间不同 */ if (mode == 1) { /* 等 worker 自己死 */ sleep(1); } else if (mode == 2) { /* 等 worker 起来 */ sleep(1); } else { /* 等 worker 起来 */ sleep(1); } printf("[main] call sm_deinit\n"); sm_deinit(); printf("[main] done\n"); return 0; }代码里面的知识点:
一张图总结"为什么"
进程要退出,worker 可能还在跑 │ ▼ 不能直接杀(丢数据、坏状态) │ ▼ 优雅退出:通知 + 等待 + 收尾 │ ├─ 通知 → abort_req ├─ 知状态 → worker_alive(加锁保护) ├─ 等待 → 轮询 + 超时 ├─ 等到了 → join + 销毁锁 └─ 等不到 → detach 兜底,不销毁锁