【发布时间】:2018-11-30 08:41:46
【问题描述】:
尝试使用函数静态互斥锁来使代码线程安全。问题不是所有编译器都以线程安全的方式初始化函数静态变量。
void Initialize()
{
static Mutex L; // can't be initialized at compile time because constructor calls CreateMutex()
L.Lock()
// call thread unsafe code
L.Unlock()
}
以下是已经考虑过的解决方案:
在全局范围内声明 Mutex,以便在 main() 之前进行初始化。不幸的是,当有一个全局变量的构造函数调用 Initialize() 时,这不起作用,因为在 C++ 中无法保证全局变量的初始化顺序
使用原子操作
void Initialize()
{
static volatile uint16_t lock=0; // trivial initialization can happen @ compile time
while (AtomicExchange(lock,(uint16_t)1)!=0); // swap lock with 1 and return previous value
// call thread unsafe code
lock=0;
}
这可行,但有忙等待的缺点
-
使用 pthread 的编译时初始化器
pthread_mutex_t lock = PTHREAD_MUTEX_INITIALIZER;
不幸的是,这是针对 Windows 的,我们正在尝试避免使用 pthread
欣赏便携的解决方案。我知道在 C++ 2011 中,函数静态初始化是线程安全的,但我们避免使用 C++ 2011,因为某些嵌入式平台可能对 C++ 2011 的支持不可靠。
【问题讨论】:
-
Volatile 与线程安全无关。您可以使用en.cppreference.com/w/c/language/atomic
-
在 C++11 之前可能没有“可移植”的方式,因为线程在 2011 年首次引入 C++。
-
4.在函数外部创建互斥体,将其作为函数参数/上下文的一部分传递。
-
显然
Initialize需要访问其他全局状态(否则您不需要锁定它)。为什么您认为“在全局范围内声明互斥锁”由于无序初始化而不起作用,而其他全局状态将被正确初始化? -
@felix boost.thread 在 C++11 之前很长一段时间都可以使用
标签: c++ multithreading static initialization mutex