1)多线程异常处理
多线程中如何捕获抛出异常到主线程
a)catch中使用std::current_exception();获得正在处理的异常
b)通过引用类型std::exception_ptr& _ex_ptr 传出
c)std::rethrow_exception(ex_ptr);重新抛出异常
using namespace std;
try {
std::exception_ptr ex_ptr;
thread th([](std::exception_ptr& _ex_ptr) {
try {
int sum = 0;
for (int i = 0; i <= 9; i++)
{
sum += i;
}
throw(std::runtime_error("error level:1"));
}
catch (std::exception& _ex)
{
_ex_ptr = std::current_exception();
//获得当前正在处理的异常
}
}, ref(ex_ptr));
th.join();
if(ex_ptr)
std::rethrow_exception(ex_ptr);
//重新抛出异常
}
catch (std::exception& ex)
{
cout << "exception:" << ex.what() << endl;
}
2)多线程中(单例类)类对象的初始化问题
a)双重检查锁定:
减少同步开销:只有在实例尚未创建时才需要获取锁,减少了锁的竞争,提高了性能。
大多数情况下,实例已经创建,第二次检查和锁的获取可以避免。
b) C++11 标准保证了静态局部变量的线程安全初始化,可以简化单例模式的实现。
class Singleton {
public:
static Singleton& getInstance() {
static Singleton instance; // 线程安全的静态局部变量
return instance;
}
private:
Singleton() {} // 私有构造函数,确保单例模式
~Singleton() {} // 私有析构函数,确保单例模式
Singleton(const Singleton&) = delete; // 禁用拷贝构造函数
Singleton& operator=(const Singleton&) = delete; // 禁用赋值操作符
};
c) call once;
C++11 提出了call_once函数,我们可以配合一个局部的静态变量once_flag实现线程安全的初始化。 多线程调用call_once函数时,会判断once_flag是否被初始化,
如没被初始化则进入初始化流程,调用我们提供的初始化函数。 但是同一时刻只有一个线程能进入这个初始化函数
class Bolala {
public:
static Bolala* get_Instance()
{
static std::once_flag s_flag;
//std::call_once(once_flag,function)
std::call_once(s_flag, []() {
bola_ptr = new Bolala();
std::cout << "once init" << std::endl;
});
return bola_ptr;
}
private:
static Bolala* bola_ptr;
};
Bolala* Bolala::bola_ptr = nullptr;
为什么 s_flag 不需要显式初始化?而bola_ptr 需要
零初始化:std::once_flag 是一个标准库提供的类型,它的默认构造函数会将其内部状态初始化为一个“未调用”状态。
这意味着 std::once_flag 在声明时已经自动初始化为一个有效的状态。
局部静态变量:s_flag 是一个局部静态变量,C++ 标准保证局部静态变量在第一次被使用前会被自动初始化。因此,你不需要显式初始化 s_flag。
C++ 标准规定,静态成员变量必须在类外部进行初始化。因此,你需要在类外部显式初始化 bola_ptr
局部静态变量:s_flag 是一个局部静态变量,C++ 标准保证局部静态变量在第一次被使用前会被自动初始化。因此,你不需要显式初始化 s_flag。
标签:std,初始化,Singleton,flag,单例,多线程,异常,ptr,once From: https://www.cnblogs.com/light-LifeClub/p/18425036