MST

星途 面试题库

面试题:C语言Linux多线程创建中的线程同步与资源管理

在一个Linux C语言项目中,有多个线程,其中一个主线程负责初始化一系列资源(如文件描述符、内存分配等),然后创建多个工作线程使用这些资源。工作线程结束后,主线程要负责释放资源。请描述如何实现线程间的同步,以确保资源在正确的时机被使用和释放,并且要考虑到异常情况下(如某个工作线程崩溃)资源的正确回收。请写出关键代码逻辑和对应的解释。
14.6万 热度难度
编程语言C

知识考点

AI 面试

面试题答案

一键面试

关键代码逻辑及解释

  1. 头文件包含
#include <pthread.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>

包含线程操作、标准输入输出、动态内存分配以及标准符号常量和类型的头文件。

  1. 全局变量定义
pthread_mutex_t resource_mutex;
pthread_cond_t resource_cond;
int resource_ready = 0;
// 模拟资源,例如文件描述符(这里用int代替)
int file_descriptor; 
// 模拟分配的内存指针
void* allocated_memory; 
  • resource_mutex:互斥锁,用于保护共享资源(如resource_ready)的访问。
  • resource_cond:条件变量,用于线程间的同步,通知工作线程资源已准备好。
  • resource_ready:标志资源是否准备好的变量。
  • file_descriptor:模拟文件描述符资源。
  • allocated_memory:模拟分配的内存资源。
  1. 工作线程函数
void* worker_thread(void* arg) {
    pthread_mutex_lock(&resource_mutex);
    while (!resource_ready) {
        pthread_cond_wait(&resource_cond, &resource_mutex);
    }
    pthread_mutex_unlock(&resource_mutex);

    // 使用资源
    printf("Worker thread is using the resources.\n");
    // 这里添加实际使用文件描述符和内存的代码

    return NULL;
}
  • 首先获取互斥锁,确保对resource_ready的检查是线程安全的。
  • 使用while循环检查resource_ready,如果资源未准备好,调用pthread_cond_wait等待条件变量。pthread_cond_wait会自动释放互斥锁,使其他线程可以修改资源状态,当条件变量被通知时,pthread_cond_wait重新获取互斥锁并返回。
  • 释放互斥锁后,工作线程可以安全地使用资源。
  1. 主线程函数
int main() {
    pthread_t worker[3];
    int i, ret;

    // 初始化互斥锁和条件变量
    pthread_mutex_init(&resource_mutex, NULL);
    pthread_cond_init(&resource_cond, NULL);

    // 初始化资源
    file_descriptor = open("test.txt", O_RDONLY);
    if (file_descriptor == -1) {
        perror("open");
        return 1;
    }
    allocated_memory = malloc(1024);
    if (allocated_memory == NULL) {
        perror("malloc");
        close(file_descriptor);
        return 1;
    }

    // 创建工作线程
    for (i = 0; i < 3; i++) {
        ret = pthread_create(&worker[i], NULL, worker_thread, NULL);
        if (ret != 0) {
            perror("pthread_create");
            free(allocated_memory);
            close(file_descriptor);
            return 1;
        }
    }

    // 标记资源已准备好
    pthread_mutex_lock(&resource_mutex);
    resource_ready = 1;
    pthread_cond_broadcast(&resource_cond);
    pthread_mutex_unlock(&resource_mutex);

    // 等待工作线程结束
    for (i = 0; i < 3; i++) {
        ret = pthread_join(worker[i], NULL);
        if (ret != 0) {
            perror("pthread_join");
            // 如果某个工作线程崩溃,这里可以添加额外的错误处理逻辑
            // 例如尝试清理未完成的工作或标记资源为需要清理
        }
    }

    // 释放资源
    free(allocated_memory);
    close(file_descriptor);

    // 销毁互斥锁和条件变量
    pthread_mutex_destroy(&resource_mutex);
    pthread_cond_destroy(&resource_cond);

    return 0;
}
  • 初始化互斥锁和条件变量。
  • 初始化资源(打开文件、分配内存),并检查初始化是否成功,失败则进行相应的错误处理并释放已分配的资源。
  • 创建多个工作线程,并检查创建是否成功,失败则进行相应的错误处理并释放已分配的资源。
  • 使用互斥锁保护resource_ready变量,将其设置为1表示资源已准备好,并通过pthread_cond_broadcast通知所有等待的工作线程。
  • 使用pthread_join等待所有工作线程结束。如果某个工作线程崩溃,pthread_join会返回错误,可以在错误处理中添加额外的清理逻辑。
  • 工作线程结束后,释放资源(关闭文件描述符、释放内存)。
  • 销毁互斥锁和条件变量。

通过以上代码逻辑,可以实现线程间的同步,确保资源在正确的时机被使用和释放,并且在异常情况下(如某个工作线程崩溃)也能尽量保证资源的正确回收。