1. 类定义及回调函数实现
#include <iostream>
#include <vector>
#include <mutex>
#include <thread>
#include <functional>
#include <queue>
// 自定义类
class CustomClass {
public:
int data;
CustomClass(int d) : data(d) {}
};
class WorkerClass {
private:
std::mutex mtx;
std::queue<std::function<void()>> taskQueue;
public:
// 回调函数,处理不同类型参数
template <typename... Args>
void workerCallback(Args&&... args) {
std::unique_lock<std::mutex> lock(mtx);
taskQueue.push([&]() {
// 这里处理实际的参数逻辑
(void)std::initializer_list<int>{((void)std::cout << "处理参数: ", 0)...};
});
}
// 模拟多线程触发回调的执行函数
void executeTasks() {
while (true) {
std::function<void()> task;
{
std::unique_lock<std::mutex> lock(mtx);
if (taskQueue.empty()) break;
task = std::move(taskQueue.front());
taskQueue.pop();
}
task();
}
}
};
2. 多线程触发回调的代码示例
int main() {
WorkerClass worker;
std::vector<std::thread> threads;
// 模拟多个线程触发回调
for (int i = 0; i < 5; ++i) {
threads.emplace_back([&worker, i]() {
if (i % 2 == 0) {
std::vector<int> vec = {1, 2, 3};
worker.workerCallback(vec);
} else {
CustomClass obj(i);
worker.workerCallback(obj);
}
});
}
std::thread executor(&WorkerClass::executeTasks, &worker);
for (auto& th : threads) {
th.join();
}
// 等待任务队列处理完毕
executor.join();
return 0;
}
3. 线程安全措施及其原理
- 互斥锁(
std::mutex
):在 WorkerClass
类中定义了一个 std::mutex
成员变量 mtx
。在 workerCallback
函数中,使用 std::unique_lock<std::mutex>
来锁定互斥锁 mtx
。这确保了在多线程环境下,对 taskQueue
的操作(如入队操作)是线程安全的。因为同一时间只有一个线程能够获取到锁,其他试图获取锁的线程会被阻塞,从而避免了数据竞争。
- 任务队列(
std::queue<std::function<void()>>
):通过将不同类型参数的处理逻辑封装成 std::function<void()>
放入任务队列 taskQueue
中。这样做的好处是,在多线程触发回调时,只需要将任务放入队列,而实际的处理逻辑在一个单独的线程(这里通过 executeTasks
函数模拟)中按顺序执行,进一步避免了多线程并发处理参数时可能产生的数据竞争。同时,executeTasks
函数在从任务队列中取出任务时,也使用了互斥锁来保证线程安全。