MST

星途 面试题库

面试题:并发与同步:使用计数器实现复杂同步逻辑

假设你正在开发一个多线程的任务调度系统,不同类型的任务有不同的优先级。请设计一个基于计数器的同步机制,确保高优先级任务优先执行,并且在任务执行过程中避免资源竞争,阐述具体实现思路和关键代码逻辑。
17.5万 热度难度
操作系统并发与同步

知识考点

AI 面试

面试题答案

一键面试

实现思路

  1. 任务优先级定义:为不同类型任务设定优先级,例如高、中、低。
  2. 计数器设计:使用计数器记录高优先级任务数量。当高优先级任务加入队列时,计数器增加;任务开始执行时,计数器减少。
  3. 同步机制:使用互斥锁来保护共享资源,避免资源竞争。利用条件变量来实现线程间的同步,当高优先级任务计数器为0时,低优先级任务才能执行。

关键代码逻辑(以C++为例)

#include <iostream>
#include <thread>
#include <queue>
#include <mutex>
#include <condition_variable>
#include <chrono>

// 任务结构体
struct Task {
    int priority;
    std::function<void()> func;
    Task(int p, std::function<void()> f) : priority(p), func(f) {}
};

std::mutex mtx;
std::condition_variable cv;
std::queue<Task> taskQueue;
int highPriorityCount = 0;

// 任务生产者
void producer() {
    for (int i = 0; i < 10; ++i) {
        std::this_thread::sleep_for(std::chrono::milliseconds(100));
        int priority = (i % 3 == 0)? 1 : 0; // 每3个任务中有1个高优先级任务
        std::function<void()> taskFunc = [i]() {
            std::cout << "Task " << i << " is running." << std::endl;
            std::this_thread::sleep_for(std::chrono::milliseconds(200));
        };
        Task task(priority, taskFunc);
        std::unique_lock<std::mutex> lock(mtx);
        taskQueue.push(task);
        if (priority == 1) {
            highPriorityCount++;
        }
        lock.unlock();
        cv.notify_one();
    }
}

// 任务消费者
void consumer() {
    while (true) {
        std::unique_lock<std::mutex> lock(mtx);
        cv.wait(lock, [] { return!taskQueue.empty(); });
        Task task = taskQueue.front();
        taskQueue.pop();
        if (task.priority == 1) {
            highPriorityCount--;
        } else {
            cv.wait(lock, [] { return highPriorityCount == 0; });
        }
        lock.unlock();
        task.func();
        if (taskQueue.empty()) break;
    }
}

在主函数中启动生产者和消费者线程:

int main() {
    std::thread producerThread(producer);
    std::thread consumerThread(consumer);
    producerThread.join();
    consumerThread.join();
    return 0;
}

在上述代码中:

  1. Task结构体用于封装任务及其优先级。
  2. producer函数模拟任务的生产,将任务加入队列,并根据优先级更新highPriorityCount
  3. consumer函数从队列中取出任务,高优先级任务直接执行并减少计数器,低优先级任务等待直到高优先级任务计数器为0。
  4. 使用std::mutexstd::condition_variable确保线程安全和同步。