MST

星途 面试题库

面试题:C语言Linux定时器组的冲突处理

假设在Linux C语言实现的定时器组中,多个定时器设置的触发时间非常接近甚至相同,可能会导致资源竞争和调度冲突,你会如何设计机制来避免或处理这种冲突?请详细说明思路和可能用到的数据结构及函数。
46.9万 热度难度
编程语言C

知识考点

AI 面试

面试题答案

一键面试

思路

  1. 时间轮算法:使用时间轮数据结构,将时间划分为多个槽位,每个槽位对应一定的时间间隔。定时器根据其触发时间被分配到相应的槽位中。这样,在同一时间间隔内触发的定时器会被放在同一个槽位中,方便统一处理。
  2. 优先级队列:使用优先级队列(如最小堆),以定时器的触发时间作为优先级。当定时器触发时间接近或相同时,按照优先级队列的特性,触发时间最早的定时器会优先被处理。
  3. 互斥锁:对于共享资源的访问,使用互斥锁进行保护。当一个定时器访问共享资源时,加锁防止其他定时器同时访问,避免资源竞争。

数据结构

  1. 时间轮
struct timer_slot {
    struct timer *head;
    struct timer *tail;
};

struct time_wheel {
    struct timer_slot *slots;
    int wheel_size;
    int current_slot;
};
  1. 优先级队列(最小堆)
struct timer {
    unsigned long expire_time;
    void (*callback)(void *);
    void *data;
    struct timer *next;
};

struct priority_queue {
    struct timer **heap;
    int size;
    int capacity;
};
  1. 互斥锁
pthread_mutex_t mutex;

函数

  1. 时间轮相关函数
// 初始化时间轮
struct time_wheel* init_time_wheel(int size) {
    struct time_wheel *tw = (struct time_wheel*)malloc(sizeof(struct time_wheel));
    tw->wheel_size = size;
    tw->current_slot = 0;
    tw->slots = (struct timer_slot*)malloc(size * sizeof(struct timer_slot));
    for (int i = 0; i < size; i++) {
        tw->slots[i].head = NULL;
        tw->slots[i].tail = NULL;
    }
    return tw;
}

// 添加定时器到时间轮
void add_timer_to_time_wheel(struct time_wheel *tw, struct timer *timer, unsigned long expire_time) {
    int slot = (expire_time + tw->current_slot) % tw->wheel_size;
    if (tw->slots[slot].head == NULL) {
        tw->slots[slot].head = timer;
        tw->slots[slot].tail = timer;
    } else {
        tw->slots[slot].tail->next = timer;
        tw->slots[slot].tail = timer;
    }
}

// 时间轮推进
void advance_time_wheel(struct time_wheel *tw) {
    tw->current_slot = (tw->current_slot + 1) % tw->wheel_size;
    struct timer *timer = tw->slots[tw->current_slot].head;
    while (timer != NULL) {
        struct timer *next = timer->next;
        timer->callback(timer->data);
        free(timer);
        timer = next;
    }
    tw->slots[tw->current_slot].head = NULL;
    tw->slots[tw->current_slot].tail = NULL;
}
  1. 优先级队列相关函数
// 初始化优先级队列
struct priority_queue* init_priority_queue(int capacity) {
    struct priority_queue *pq = (struct priority_queue*)malloc(sizeof(struct priority_queue));
    pq->size = 0;
    pq->capacity = capacity;
    pq->heap = (struct timer**)malloc(capacity * sizeof(struct timer*));
    return pq;
}

// 向优先级队列添加定时器
void add_timer_to_priority_queue(struct priority_queue *pq, struct timer *timer) {
    if (pq->size == pq->capacity) {
        // 可扩展队列大小
        return;
    }
    pq->heap[pq->size++] = timer;
    int index = pq->size - 1;
    while (index > 0 && pq->heap[(index - 1) / 2]->expire_time > pq->heap[index]->expire_time) {
        struct timer *temp = pq->heap[(index - 1) / 2];
        pq->heap[(index - 1) / 2] = pq->heap[index];
        pq->heap[index] = temp;
        index = (index - 1) / 2;
    }
}

// 从优先级队列获取并移除最早到期的定时器
struct timer* get_and_remove_timer_from_priority_queue(struct priority_queue *pq) {
    if (pq->size == 0) {
        return NULL;
    }
    struct timer *timer = pq->heap[0];
    pq->heap[0] = pq->heap[--pq->size];
    int index = 0;
    while (index * 2 + 1 < pq->size) {
        int left = index * 2 + 1;
        int right = index * 2 + 2;
        int smallest = index;
        if (pq->heap[left]->expire_time < pq->heap[smallest]->expire_time) {
            smallest = left;
        }
        if (right < pq->size && pq->heap[right]->expire_time < pq->heap[smallest]->expire_time) {
            smallest = right;
        }
        if (smallest != index) {
            struct timer *temp = pq->heap[index];
            pq->heap[index] = pq->heap[smallest];
            pq->heap[smallest] = temp;
            index = smallest;
        } else {
            break;
        }
    }
    return timer;
}
  1. 互斥锁相关函数
// 初始化互斥锁
void init_mutex() {
    pthread_mutex_init(&mutex, NULL);
}

// 加锁
void lock_mutex() {
    pthread_mutex_lock(&mutex);
}

// 解锁
void unlock_mutex() {
    pthread_mutex_unlock(&mutex);
}