面试题答案
一键面试资源竞争问题分析
在多线程环境下,多个线程可能同时尝试调用同一个对象的不同析构函数重载,这会导致对共享资源(如数据库连接、共享内存段)的并发访问,从而引发资源竞争问题。例如,一个线程正在释放数据库连接,而另一个线程同时尝试释放共享内存段,可能导致数据不一致或资源泄漏。
同步机制解决方案
- 互斥锁(Mutex):使用互斥锁可以保证在同一时间只有一个线程能够进入临界区(析构函数体),从而避免资源竞争。
- 避免死锁:为了避免死锁,需要遵循一些原则,如按相同顺序获取锁,避免嵌套锁等。
代码示例
#include <iostream>
#include <mutex>
#include <thread>
// 模拟数据库连接资源
class DatabaseConnection {
public:
DatabaseConnection() { std::cout << "Database connection created." << std::endl; }
~DatabaseConnection() { std::cout << "Database connection released." << std::endl; }
};
// 模拟共享内存段资源
class SharedMemorySegment {
public:
SharedMemorySegment() { std::cout << "Shared memory segment created." << std::endl; }
~SharedMemorySegment() { std::cout << "Shared memory segment released." << std::endl; }
};
class ResourceManager {
private:
DatabaseConnection* dbConn;
SharedMemorySegment* shmSeg;
std::mutex resourceMutex;
public:
ResourceManager() : dbConn(new DatabaseConnection()), shmSeg(new SharedMemorySegment()) {}
~ResourceManager() {
std::lock_guard<std::mutex> lock(resourceMutex);
if (dbConn) {
delete dbConn;
dbConn = nullptr;
}
if (shmSeg) {
delete shmSeg;
shmSeg = nullptr;
}
}
// 模拟不同析构函数重载(这里实际使用一个析构函数,但逻辑类似多个析构操作)
void releaseDatabaseConnection() {
std::lock_guard<std::mutex> lock(resourceMutex);
if (dbConn) {
delete dbConn;
dbConn = nullptr;
}
}
void releaseSharedMemorySegment() {
std::lock_guard<std::mutex> lock(resourceMutex);
if (shmSeg) {
delete shmSeg;
shmSeg = nullptr;
}
}
};
void threadFunction1(ResourceManager* rm) {
rm->releaseDatabaseConnection();
}
void threadFunction2(ResourceManager* rm) {
rm->releaseSharedMemorySegment();
}
int main() {
ResourceManager rm;
std::thread t1(threadFunction1, &rm);
std::thread t2(threadFunction2, &rm);
t1.join();
t2.join();
return 0;
}
在上述代码中,ResourceManager
类使用一个互斥锁resourceMutex
来保护对数据库连接和共享内存段的释放操作。releaseDatabaseConnection
和releaseSharedMemorySegment
函数通过std::lock_guard
来自动获取和释放锁,确保同一时间只有一个线程能够访问和释放资源,从而避免资源竞争。同时,由于只有一个锁,不会出现死锁问题。如果存在多个锁,获取锁的顺序应保持一致以避免死锁。