MST

星途 面试题库

面试题:C语言Linux多线程资源动态管理优化

在Linux C语言多线程环境下,当共享资源的数量动态变化(例如根据运行时的负载情况增加或减少资源)时,如何设计一种高效的资源管理机制,以确保线程安全且尽可能减少锁争用带来的性能损耗?请从数据结构设计、锁策略以及线程调度等方面阐述你的思路,并提供关键代码示例。
20.6万 热度难度
编程语言C

知识考点

AI 面试

面试题答案

一键面试

数据结构设计

  1. 使用链表
    • 链表可以方便地进行动态插入和删除操作,适合共享资源数量动态变化的场景。例如,定义一个表示共享资源的结构体,并将其组织成链表。
    struct Resource {
        // 资源相关数据
        void* data;
        struct Resource* next;
    };
    struct Resource* resource_list = NULL;
    
  2. 使用哈希表
    • 如果资源有唯一标识,可以使用哈希表来快速定位资源。在Linux下可以使用glib的GHashTable
    • 例如,假设资源有一个整数ID:
    #include <glib.h>
    GHashTable* resource_hash_table = g_hash_table_new(g_direct_hash, g_direct_equal);
    // 插入资源
    g_hash_table_insert(resource_hash_table, GINT_TO_POINTER(resource_id), resource_ptr);
    // 获取资源
    struct Resource* resource = g_hash_table_lookup(resource_hash_table, GINT_TO_POINTER(resource_id));
    

锁策略

  1. 读写锁(Read - Write Lock)
    • 当大部分操作是读取共享资源,而只有少数操作是修改(增加或减少资源)时,使用读写锁可以提高性能。读操作可以并发执行,写操作则需要独占锁。
    #include <pthread.h>
    pthread_rwlock_t rwlock;
    pthread_rwlock_init(&rwlock, NULL);
    // 读操作
    pthread_rwlock_rdlock(&rwlock);
    // 读取共享资源代码
    pthread_rwlock_unlock(&rwlock);
    // 写操作
    pthread_rwlock_wrlock(&rwlock);
    // 修改共享资源代码(增加或减少资源)
    pthread_rwlock_unlock(&rwlock);
    
  2. 细粒度锁
    • 对于链表结构的共享资源,可以为每个资源节点设置一把锁,而不是对整个链表使用一把锁。这样可以减少锁争用。
    struct Resource {
        // 资源相关数据
        void* data;
        struct Resource* next;
        pthread_mutex_t lock;
    };
    // 访问某个资源节点
    pthread_mutex_lock(&resource_node->lock);
    // 操作资源节点数据
    pthread_mutex_unlock(&resource_node->lock);
    

线程调度

  1. 线程池
    • 使用线程池可以减少线程创建和销毁的开销,并且可以对线程进行统一调度。在Linux下可以使用libuv等库来实现线程池。
    • 例如,使用libuv创建线程池:
    #include <uv.h>
    uv_loop_t* loop = uv_default_loop();
    uv_work_t work_req;
    // 定义工作函数
    void work_callback(uv_work_t* req) {
        // 处理共享资源的工作
    }
    void after_work_callback(uv_work_t* req, int status) {
        // 工作完成后的回调
    }
    uv_queue_work(loop, &work_req, work_callback, after_work_callback);
    uv_run(loop, UV_RUN_DEFAULT);
    
  2. 优先级调度
    • 根据任务的优先级来调度线程对共享资源的访问。可以为每个线程分配一个优先级,在调度时优先执行高优先级线程的任务。
    • 例如,在POSIX线程中设置线程优先级:
    pthread_t thread;
    struct sched_param param;
    param.sched_priority = 99; // 高优先级
    pthread_setschedparam(thread, SCHED_FIFO, &param);
    

关键代码示例整合

#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>

// 共享资源结构体
struct Resource {
    int data;
    struct Resource* next;
    pthread_mutex_t lock;
};

// 链表头
struct Resource* resource_list = NULL;
pthread_rwlock_t rwlock;

// 添加资源函数
void add_resource(int new_data) {
    struct Resource* new_resource = (struct Resource*)malloc(sizeof(struct Resource));
    new_resource->data = new_data;
    new_resource->next = NULL;
    pthread_mutex_init(&new_resource->lock, NULL);

    pthread_rwlock_wrlock(&rwlock);
    if (resource_list == NULL) {
        resource_list = new_resource;
    } else {
        struct Resource* current = resource_list;
        while (current->next != NULL) {
            current = current->next;
        }
        current->next = new_resource;
    }
    pthread_rwlock_unlock(&rwlock);
}

// 删除资源函数
void delete_resource(int target_data) {
    pthread_rwlock_wrlock(&rwlock);
    struct Resource* current = resource_list;
    struct Resource* prev = NULL;
    while (current != NULL && current->data != target_data) {
        prev = current;
        current = current->next;
    }
    if (current != NULL) {
        if (prev == NULL) {
            resource_list = current->next;
        } else {
            prev->next = current->next;
        }
        pthread_mutex_destroy(&current->lock);
        free(current);
    }
    pthread_rwlock_unlock(&rwlock);
}

// 读取资源函数
void read_resource() {
    pthread_rwlock_rdlock(&rwlock);
    struct Resource* current = resource_list;
    while (current != NULL) {
        pthread_mutex_lock(&current->lock);
        printf("Resource data: %d\n", current->data);
        pthread_mutex_unlock(&current->lock);
        current = current->next;
    }
    pthread_rwlock_unlock(&rwlock);
}

// 线程函数
void* thread_function(void* arg) {
    add_resource(10);
    read_resource();
    delete_resource(10);
    return NULL;
}

int main() {
    pthread_rwlock_init(&rwlock, NULL);
    pthread_t threads[10];
    for (int i = 0; i < 10; i++) {
        pthread_create(&threads[i], NULL, thread_function, NULL);
    }
    for (int i = 0; i < 10; i++) {
        pthread_join(threads[i], NULL);
    }
    pthread_rwlock_destroy(&rwlock);
    return 0;
}

上述代码展示了如何通过数据结构(链表)、锁策略(读写锁和细粒度锁)以及多线程操作来实现共享资源的动态管理,同时保证线程安全并减少锁争用。