面试题答案
一键面试可能出现的问题
- 线程安全问题:如果多个线程同时访问和修改同一个随机数生成器的状态,可能会导致数据竞争,产生未定义行为。
- 随机数分布不均匀:如果使用简单的伪随机数生成器,且没有正确初始化种子,可能会导致不同线程生成的随机数分布不均匀。
解决方案
- 使用合适的随机数生成器:C++11 引入了
<random>
库,提供了多种随机数生成器和分布。例如,std::mt19937
是一个常用的伪随机数生成器,具有良好的统计特性。 - 同步机制:为了避免线程安全问题,可以为每个线程创建独立的随机数生成器实例,这样就不需要同步。如果必须共享一个生成器,可以使用互斥锁(
std::mutex
)进行保护。
以下是为每个线程创建独立随机数生成器实例的代码示例:
#include <iostream>
#include <thread>
#include <random>
#include <vector>
void thread_function(int id) {
// 使用不同的种子初始化每个线程的随机数生成器
std::random_device rd;
std::mt19937 gen(rd() + id);
std::uniform_int_distribution<> distrib(1, 100);
// 生成并输出随机数
for (int i = 0; i < 5; ++i) {
std::cout << "Thread " << id << " generated: " << distrib(gen) << std::endl;
}
}
int main() {
const int num_threads = 3;
std::vector<std::thread> threads;
for (int i = 0; i < num_threads; ++i) {
threads.emplace_back(thread_function, i);
}
for (auto& thread : threads) {
thread.join();
}
return 0;
}
验证解决方案的正确性
- 统计验证:收集大量不同线程生成的随机数,然后进行统计分析,例如计算均值、方差,绘制直方图等,验证随机数是否符合预期的分布。
- 重现验证:多次运行程序,观察不同线程生成的随机数是否每次都不同,且分布均匀。如果每次运行结果都相似,可能存在种子初始化问题。
- 代码审查:仔细检查代码,确保每个线程独立初始化随机数生成器,没有共享状态导致线程安全问题。