面试题答案
一键面试设计思路
- 避免竞争条件:使用互斥锁(
std::mutex
)来保护文件操作。当一个线程想要打开、读取、写入或关闭文件时,首先获取互斥锁,操作完成后释放互斥锁。这样可以确保同一时间只有一个线程能够访问文件,避免数据不一致。 - 优化文件打开关闭开销:
- 文件缓存:对于频繁打开关闭文件的场景,可以考虑使用文件缓存。在内存中维护一个缓存区,当需要读取文件时,先检查缓存中是否存在所需数据,如果存在则直接从缓存读取;当需要写入文件时,先写入缓存,达到一定条件(如缓存满、定时等)再批量写入文件。
- 延迟关闭:在可能的情况下,延迟文件关闭操作。例如,在一个短时间内预计会再次使用该文件时,不立即关闭文件,而是保持文件打开状态,直到确定一段时间内不会再使用它。
关键代码片段
#include <iostream>
#include <fstream>
#include <mutex>
#include <unordered_map>
#include <thread>
std::mutex fileMutex;
// 简单的文件缓存,这里用unordered_map模拟
std::unordered_map<std::string, std::string> fileCache;
// 从文件读取数据
std::string readFile(const std::string& filePath) {
std::lock_guard<std::mutex> lock(fileMutex);
// 先检查缓存
if (fileCache.find(filePath) != fileCache.end()) {
return fileCache[filePath];
}
std::ifstream file(filePath);
if (!file.is_open()) {
throw std::runtime_error("Could not open file: " + filePath);
}
std::string content((std::istreambuf_iterator<char>(file)), std::istreambuf_iterator<char>());
file.close();
// 缓存数据
fileCache[filePath] = content;
return content;
}
// 写入数据到文件
void writeFile(const std::string& filePath, const std::string& content) {
std::lock_guard<std::mutex> lock(fileMutex);
// 先写入缓存
fileCache[filePath] = content;
// 这里可以添加逻辑,如缓存满时才真正写入文件
std::ofstream file(filePath);
if (!file.is_open()) {
throw std::runtime_error("Could not open file: " + filePath);
}
file << content;
file.close();
}
// 示例函数,用于模拟多线程操作
void threadFunction(const std::string& filePath, const std::string& writeContent = "") {
if (!writeContent.empty()) {
writeFile(filePath, writeContent);
}
std::string data = readFile(filePath);
std::cout << "Thread read: " << data << std::endl;
}
int main() {
std::string filePath = "test.txt";
std::thread t1(threadFunction, filePath, "Initial content");
std::thread t2(threadFunction, filePath);
t1.join();
t2.join();
return 0;
}
上述代码通过std::mutex
来避免竞争条件,并通过简单的文件缓存机制优化频繁打开关闭文件的开销。在实际应用中,文件缓存的实现可能需要更复杂的策略,例如LRU(最近最少使用)算法来管理缓存空间等。