关于在main()外及其他.c文件中使用mutexes与semaphores的初始化销毁位置咨询
关于互斥锁与信号量的初始化/销毁时机问题
首先明确:绝对不能在每个自定义函数内重复调用初始化和销毁函数,这种写法完全错误,原因如下:
- 重复初始化已处于初始化状态的互斥锁/信号量属于未定义行为,可能直接导致程序崩溃或死锁。
- 销毁同步对象后,后续再对其进行加锁/等待操作同样是未定义行为,会引发不可预测的问题。
- 每个函数内初始化的同步对象是独立实例,根本无法实现跨线程的同步效果。
正确的调用时机与方式
互斥锁和信号量是全局生命周期的同步工具,必须遵循「所有线程启动前初始化,所有线程结束后销毁」的原则,具体实现分两种场景:
场景1:动态初始化(推荐,兼容性更强)
在自定义函数所在的.c文件中定义全局同步对象,再提供专门的初始化/销毁函数,由main()函数在合适时机调用:
// custom.c #include <pthread.h> #include <semaphore.h> // 全局同步对象,供所有自定义函数共享 pthread_mutex_t g_sync_mutex; sem_t g_sync_sem; // 初始化同步对象的函数,需在所有线程创建前调用 void sync_init() { // 初始化互斥锁,使用默认属性 pthread_mutex_init(&g_sync_mutex, NULL); // 初始化信号量:第二个参数0表示线程间共享,第三个参数是初始值 sem_init(&g_sync_sem, 0, 1); } // 销毁同步对象的函数,需在所有线程结束后调用 void sync_destroy() { pthread_mutex_destroy(&g_sync_mutex); sem_destroy(&g_sync_sem); } // 自定义函数,使用同步对象 void my_custom_func() { pthread_mutex_lock(&g_sync_mutex); // 临界区代码:需要互斥访问的逻辑 pthread_mutex_unlock(&g_sync_mutex); sem_wait(&g_sync_sem); // 信号量保护的代码:控制并发访问数量的逻辑 sem_post(&g_sync_sem); }
对应的main()函数逻辑:
// main.c #include "custom.h" #include <pthread.h> int main() { // 先初始化所有同步对象 sync_init(); // 创建工作线程,线程执行逻辑中会调用my_custom_func等函数 pthread_t thread1, thread2; pthread_create(&thread1, NULL, (void*)my_custom_func, NULL); pthread_create(&thread2, NULL, (void*)my_custom_func, NULL); // 等待所有线程执行完毕 pthread_join(thread1, NULL); pthread_join(thread2, NULL); // 最后销毁同步对象 sync_destroy(); return 0; }
场景2:静态初始化(仅互斥锁适用)
互斥锁支持通过宏PTHREAD_MUTEX_INITIALIZER进行静态初始化,无需调用pthread_mutex_init,但销毁仍需在所有线程结束后执行:
// custom.c #include <pthread.h> #include <semaphore.h> // 静态初始化互斥锁 pthread_mutex_t g_sync_mutex = PTHREAD_MUTEX_INITIALIZER; // 信号量仍需动态初始化 sem_t g_sync_sem; void sync_init() { sem_init(&g_sync_sem, 0, 1); } void sync_destroy() { pthread_mutex_destroy(&g_sync_mutex); sem_destroy(&g_sync_sem); } // 自定义函数逻辑同上
补充说明
- 如果你尝试在
.c文件顶部直接调用初始化函数(比如在全局作用域写pthread_mutex_init(&g_mutex, NULL);),这是不允许的——全局作用域只能执行变量初始化,不能直接调用函数(C标准不支持)。 - 销毁操作必须等待所有使用同步对象的线程完全退出后再执行,否则会导致线程操作已销毁的对象,引发异常。
内容的提问来源于stack exchange,提问作者DualisticDev
相关产品推荐
相关产品推荐

