如何以线程安全的方式初始化C ++全局互斥锁

时间:2018-11-30 08:41:46

标签: c++ multithreading static initialization mutex

尝试使用函数静态互斥锁使代码线程安全。问题在于,并非所有编译器都以线程安全的方式初始化函数静态变量。

void Initialize()
{
  static Mutex L;   // can't be initialized at compile time because constructor calls CreateMutex()
  L.Lock()
  // call thread unsafe code
  L.Unlock()
}

以下是已经考虑的解决方案:

  1. 在全局范围内声明Mutex,以便初始化发生在main()之前。不幸的是,当存在构造函数调用Initialize()的全局变量时,这是行不通的,因为在C ++中不能保证初始化全局变量的顺序

  2. 使用原子操作

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; }

这可行,但缺点是忙于等待

  1. 使用pthread的编译时初始化程序

    pthread_mutex_t锁= PTHREAD_MUTEX_INITIALIZER;

不幸的是,这是针对Windows的,我们正在尝试避免使用pthread

欣赏便携式的解决方案。我知道在C ++ 2011中,函数静态初始化是线程安全的,但是我们避免使用C ++ 2011,因为某些嵌入式平台可能没有可靠的C ++ 2011支持。

1 个答案:

答案 0 :(得分:0)

IMO,解决您的问题的方法是使用一个漂亮的计数器惯用法。这个成语在这里得到很好的描述:https://en.wikibooks.org/wiki/More_C%2B%2B_Idioms/Nifty_Counter

使用该惯用法std::coutstd::cerrstd::clog流被初始化。唯一的要求是您需要正确计算所创建类型的对齐方式。使用该对齐方式,您需要创建一个全局缓冲区。使用该缓冲区,可以创建具有所需位置类型的实例new运算符。 Boost和Modern C ++(> = C ++ 11)具有(std|boost)::aligned_storage模板类,可为您创建正确对齐的缓冲区。请参考:

现代C ++版本具有alignof运算符,该运算符可用于计算特定类型的对齐方式。在boost中,您需要使用类型特征alignment_ofhttps://www.boost.org/doc/libs/1_69_0/libs/type_traits/doc/html/boost_typetraits/reference/alignment_of.htmlalignment_of类型特征也是现代C ++中STL的一部分,但是在这种特殊情况下,alignof运算符更易于使用。