以下是一个使用 C++ 实现的线程安全单例模式示例,结合配置管理器的经典场景,并附带完整测试代码:
#include <iostream>
#include <unordered_map>
#include <mutex>
#include <thread>
#include <vector>
#include <cassert>
// 配置管理器单例类
class ConfigurationManager {
private:
// 私有化默认构造函数
ConfigurationManager() = default;
// 删除拷贝构造函数和赋值运算符
ConfigurationManager(const ConfigurationManager&) = delete;
ConfigurationManager& operator=(const ConfigurationManager&) = delete;
// 配置存储容器
std::unordered_map<std::string, std::string> configs_;
mutable std::mutex mutex_;
public:
// 获取单例实例的引用(C++11 起静态局部变量初始化是线程安全的)
static ConfigurationManager& getInstance() {
static ConfigurationManager instance;
return instance;
}
// 设置配置项
void setConfig(const std::string& key, const std::string& value) {
std::lock_guard<std::mutex> lock(mutex_);
configs_[key] = value;
}
// 获取配置项
std::string getConfig(const std::string& key) const {
std::lock_guard<std::mutex> lock(mutex_);
auto it = configs_.find(key);
return it != configs_.end() ? it->second : "";
}
// 打印所有配置(测试用)
void printAllConfigs() const {
std::lock_guard<std::mutex> lock(mutex_);
std::cout << "Current Configurations:\n";
for (const auto& pair : configs_) {
std::cout << pair.first << " = " << pair.second << "\n";
}
}
};
// 测试单例模式的基本功能
void testBasicFunctionality() {
auto& config = ConfigurationManager::getInstance();
// 测试设置和获取配置
config.setConfig("ServerIP", "192.168.1.100");
config.setConfig("Port", "8080");
// 验证配置存储
assert(config.getConfig("ServerIP") == "192.168.1.100");
assert(config.getConfig("Port") == "8080");
// 测试单例实例的唯一性
auto& anotherRef = ConfigurationManager::getInstance();
assert(&config == &anotherRef);
// 修改配置并验证
anotherRef.setConfig("Timeout", "5000");
assert(config.getConfig("Timeout") == "5000");
std::cout << "Basic functionality tests passed!\n";
}
// 多线程测试函数
void threadTest(int threadId) {
auto& config = ConfigurationManager::getInstance();
// 写入线程特定的配置
config.setConfig("Thread" + std::to_string(threadId),
"Data" + std::to_string(threadId));
// 验证单例地址一致性
static std::mutex coutMutex;
{
std::lock_guard<std::mutex> lock(coutMutex);
std::cout << "Thread " << threadId
<< " instance address: " << &config << "\n";
}
}
// 多线程测试
void testMultithreadedAccess() {
constexpr int numThreads = 5;
std::vector<std::thread> threads;
// 创建多个线程访问单例
for (int i = 0; i < numThreads; ++i) {
threads.emplace_back(threadTest, i);
}
// 等待所有线程完成
for (auto& t : threads) {
t.join();
}
// 验证所有线程写入的配置
auto& config = ConfigurationManager::getInstance();
for (int i = 0; i < numThreads; ++i) {
const std::string key = "Thread" + std::to_string(i);
assert(config.getConfig(key) == "Data" + std::to_string(i));
}
std::cout << "Multithreaded tests passed!\n";
}
int main() {
// 运行基本功能测试
testBasicFunctionality();
// 运行多线程测试
testMultithreadedAccess();
// 打印最终配置状态
std::cout << "\nFinal configuration state:\n";
ConfigurationManager::getInstance().printAllConfigs();
return 0;
}
代码说明
-
单例实现特点:
- 使用静态局部变量实现(C++11 起线程安全)
- 删除拷贝构造函数和赋值运算符
- 使用互斥锁保证配置操作的线程安全
- 提供配置管理的基本接口(设置、获取、打印)
-
测试内容包括:
- 单例实例唯一性验证
- 基本配置操作测试
- 多线程并发访问测试
- 线程安全验证(配置项的并发读写)
-
经典场景应用:
- 作为配置管理器,集中管理应用程序的配置信息
- 支持多线程环境下的安全访问
- 全局唯一访问点保证配置一致性
测试输出示例
Basic functionality tests passed!
Thread 0 instance address: 0x1008b4050
Thread 2 instance address: 0x1008b4050
Thread 1 instance address: 0x1008b4050
Thread 3 instance address: 0x1008b4050
Thread 4 instance address: 0x1008b4050
Multithreaded tests passed!
Final configuration state:
Current Configurations:
Thread4 = Data4
Thread3 = Data3
Thread2 = Data2
Thread1 = Data1
Thread0 = Data0
Timeout = 5000
Port = 8080
ServerIP = 192.168.1.100
该实现通过了以下关键验证:
- 所有获取的实例地址相同
- 多线程并发访问安全
- 不同线程写入的数据完整保存
- 基础配置功能正常工作
这个实现方案适用于需要全局统一配置管理的场景,如服务器参数配置、应用程序设置管理等,能够有效保证配置数据的一致性和线程安全性。