C++ 全局变量构造函数/析构函数是否需要线程保护?
如果我有一个类,其唯一目的是拥有全局C++ 全局变量构造函数/析构函数是否需要线程保护?,c++,multithreading,thread-safety,C++,Multithreading,Thread Safety,如果我有一个类,其唯一目的是拥有全局静态实例(以确保其构造函数中的代码在main之前运行),并且它使用一个类静态变量,那么是否需要通过互斥来保护对该变量的访问 举个例子有助于: class WinSock { public: WinSock() { if(!(inst++)) //winsock init } ~WinSock() { if(!--inst) //winsock deactivate } private: sta
静态
实例(以确保其构造函数中的代码在main
之前运行),并且它使用一个类静态
变量,那么是否需要通过互斥来保护对该变量的访问
举个例子有助于:
class WinSock
{
public:
WinSock()
{
if(!(inst++))
//winsock init
}
~WinSock()
{
if(!--inst)
//winsock deactivate
}
private:
static int inst = 0;
}
static WinSock unusedWinSockVar;
所有这些都包含在使用winsock的任何文件所包含的头中。对
inst
的访问是否需要保护,或者该代码不可能从多个线程运行,因为线程只会创建一次main
并在main
返回之前销毁?首先,我不认为private:static int inst=0“代码>是一个有效的构造,”我的编译器大声抱怨道-如果为了简单起见,您忽略了在项目中的一些.cpp文件中有类似于int-WinSock::inst=0的内容,那么就没有问题了。如果您的项目根本无法编译,那么很可能所有转换单元都会使用不同的变量,从而导致错误的行为
其次,如果任何静态对象构造函数创建了一个新线程,那么您需要使代码线程安全。从C++标准P3.6.2:
如果程序启动线程(30.3),则
变量的初始化不按顺序排列
在不同的转换单位中定义的变量。否则
变量的初始化是不确定的
初始化在不同转换中定义的变量
单位
不确定的顺序意味着初始化不会有任何特定的顺序,但不会重叠,因此不需要任何额外的保护措施。不排序意味着不同编译UNI中的构造函数可能重叠,因此需要线程安全
第三,你需要这样做吗?您是否有其他在构造函数中使用winsock的静态对象?我真的想不出任何其他理由来这样做。首先,我不认为private:static int inst=0“代码>是一个有效的构造,”我的编译器大声抱怨道-如果为了简单起见,您忽略了在项目中的一些.cpp文件中有类似于int-WinSock::inst=0的内容,那么就没有问题了。如果您的项目根本无法编译,那么很可能所有转换单元都会使用不同的变量,从而导致错误的行为
其次,如果任何静态对象构造函数创建了一个新线程,那么您需要使代码线程安全。从C++标准P3.6.2:
如果程序启动线程(30.3),则
变量的初始化不按顺序排列
在不同的转换单位中定义的变量。否则
变量的初始化是不确定的
初始化在不同转换中定义的变量
单位
不确定的顺序意味着初始化不会有任何特定的顺序,但不会重叠,因此不需要任何额外的保护措施。不排序意味着不同编译UNI中的构造函数可能重叠,因此需要线程安全
第三,你需要这样做吗?您是否有其他在构造函数中使用winsock的静态对象?我真的想不出任何其他理由这样做。鉴于您描述的特定场景,不添加同步也可以
您担心的是Winsock在运行main
之前(之后)被初始化(和反初始化),这是肯定的。该代码也保证只从一个线程调用一次。这(事实上只有一个线程)使得同步毫无用处
假设其他静态全局对象使用Winsock(无论它们是否生成线程),这当然是不安全的,但使用互斥也不会更安全。初始化在main
因此,没有静态全局对象可以使用此构造以安全、定义良好的方式使用Winsock,因为无论哪种方式,您都不知道初始化是否首先发生。同步它不会改变这个细节
注意:不允许在类声明中初始化inst
。根据您描述的特定场景,不添加同步即可
您担心的是Winsock在运行main
之前(之后)被初始化(和反初始化),这是肯定的。该代码也保证只从一个线程调用一次。这(事实上只有一个线程)使得同步毫无用处
假设其他静态全局对象使用Winsock(无论它们是否生成线程),这当然是不安全的,但使用互斥也不会更安全。初始化在main
因此,没有静态全局对象可以使用此构造以安全、定义良好的方式使用Winsock,因为无论哪种方式,您都不知道初始化是否首先发生。同步它不会改变这个细节
注意:类声明中的inst
初始化是不允许的。我没有看到在ctor或dtor之外使用inst
,类代码是否完整?如果都在一个标题中,您不会遇到许多不同的unusedWinSockVar
的问题吗?如果它只定义了一个未使用的变量,为什么它必须包含在头文件中?任何使用WinSock
的文件都会包含这个头文件?unusedWinSockVar
是否应该在源文件中声明(为库提供内容)?@didierc确实如此