C语言主线程控制8个子线程同步循环执行的实现求助
如何实现主线程控制子线程的执行节奏?
嘿,你的需求本质上是要实现一个多线程同步屏障的变种——让所有子线程完成一轮任务后暂停,等主线程做完读取操作,再一起启动下一轮。我给你梳理两种可行的实现思路和修改后的伪代码:
方案一:使用多事件对(每个子线程两个事件)
这个方案适合用在支持事件对象的平台(比如Windows),逻辑直观,每个子线程对应一对事件:一个用来通知主线程“我完成了本轮任务”,另一个用来等待主线程“允许我继续下一轮”。
修改后的子线程伪代码
While(1) { do_something1(); // 注意:多个子线程写全局变量必须加锁,避免数据竞争! lock(g_write_mutex); set_global_variable; unlock(g_write_mutex); set_event(task_done_event[i]); // 告诉主线程:我这轮做完了 wait_event(continue_next_round_event[i]); // 等主线程发“继续”指令 reset_event(continue_next_round_event[i]); // 重置事件,准备下一轮 sleep(100); // 按需保留 }
修改后的主线程伪代码
While(1) { int i; // 先等所有子线程都完成本轮任务 for (i = 0; i < 8; i++) { wait_event(task_done_event[i]); reset_event(task_done_event[i]); // 重置事件,准备下一轮等待 } // 主线程完成读取和后续操作 read_global_variable; do_something2(); // 通知所有子线程可以启动下一轮 for (i = 0; i < 8; i++) { set_event(continue_next_round_event[i]); } sleep(100); // 按需保留 }
方案二:使用条件变量+互斥锁(POSIX线程标准方案)
如果是用POSIX线程(pthread)这类标准线程库,条件变量+互斥锁是更通用的同步方式,不需要为每个子线程创建单独的事件对象。
全局同步变量
mutex_t g_sync_mutex; cond_t g_sync_cond; int g_completed_threads = 0; // 记录完成本轮任务的子线程数量 bool g_main_ready = false; // 标记主线程是否允许子线程继续
修改后的子线程伪代码
While(1) { do_something1(); // 安全修改全局变量和计数器 lock(g_sync_mutex); set_global_variable; g_completed_threads++; unlock(g_sync_mutex); // 等待主线程完成读取并发出继续信号 lock(g_sync_mutex); while (!g_main_ready) { wait_cond(g_sync_cond, g_sync_mutex); // 等待时会自动释放锁,被唤醒后重新获取 } g_main_ready = false; // 重置标志,准备下一轮 unlock(g_sync_mutex); sleep(100); // 按需保留 }
修改后的主线程伪代码
While(1) { // 等待所有8个子线程完成本轮任务 lock(g_sync_mutex); while (g_completed_threads < 8) { wait_cond(g_sync_cond, g_sync_mutex); } g_completed_threads = 0; // 重置计数器 unlock(g_sync_mutex); // 主线程执行读取和后续操作 read_global_variable; do_something2(); // 通知所有子线程可以继续下一轮 lock(g_sync_mutex); g_main_ready = true; broadcast_cond(g_sync_cond); // 广播唤醒所有等待的子线程 unlock(g_sync_mutex); sleep(100); // 按需保留 }
关键注意事项
- 全局变量线程安全:多个子线程同时写入全局变量一定会导致数据竞争,必须用互斥锁包裹写操作,确保同一时间只有一个线程修改它。
- 状态重置:不管用事件还是条件变量,每次同步完成后都要重置对应的标志/事件状态,避免下一轮循环出现逻辑错误(比如事件一直处于触发状态,导致线程直接跳过等待)。
- 唤醒方式:条件变量的
broadcast操作会唤醒所有等待的线程,适合这种“所有线程一起继续”的场景;如果用signal则只会唤醒一个线程,不符合需求。
内容的提问来源于stack exchange,提问作者xksyvone
相关产品推荐
相关产品推荐

