函数中带有静态变量的竞争条件

Posted

技术标签:

【中文标题】函数中带有静态变量的竞争条件【英文标题】:Race condition with a static variable in a function 【发布时间】:2020-03-04 01:22:08 【问题描述】:

我有以下功能:

int helper(int id) 
  static std::map<int,int>* lookup_table = new std::map<int,int>();

  // Modify lookup_table

  return (it == lookup_table->end()) ? -1 : 0;

helper 在多个线程中被调用。有什么方法可以防止lookup_table 出现竞争条件?

这样就够了吗?

static std::mutex helper_lock;

int helper(int id) 
  static std::map<int,int>* lookup_table = new std::map<int,int>();

  helper_lock.lock();
  // Modify lookup_table
  helper_lock.unlock();

  return (it == lookup_table->end()) ? -1 : 0;

【问题讨论】:

为什么不编写惯用的 C++ 代码?只需使用锁定类。 等等...我看到修改是什么让你丧命。每次都修改吗?附带问题:为什么lookup_table 是动态分配的?对于库容器来说,这是一个非常不寻常(而且通常很糟糕)的选择。他们的部分工作是保护您免受手动内存管理的影响。 是的,您需要一个互斥锁来控制对静态变量的访问。而且,不,您不需要它是一个指针,并使用new 分配。无论如何,这绝对没有任何用处。 static std::map&lt;int,int&gt; lookup_table; 也能正常工作,并且可以减少您痛苦的键盘的大量磨损。最后,使用锁守卫,而不是显式锁定/解锁互斥锁。这是避免编写一堆错误的有保证且免费的方法。 【参考方案1】:

这还不够。对 STL 容器的修改可能会使其迭代器无效,因此如果另一个线程正在修改表,则与函数末尾的 lookup_table.end() 的比较可能会无效。

简单的解决方案是仅在比较完成后解锁。 (请注意,我使用 std::unique_lock&lt;std::mutex&gt; 进行锁定 - 当 unique_lock 超出范围时释放锁定

static std::mutex helper_lock;

int helper(int id) 
  static std::map<int,int>* lookup_table = new std::map<int,int>();

  std::unique_lock<std::mutex> lock(helper_lock);
  // Modify lookup_table
  // explicit unlock is not required, lock is released when lock is destroyed

  return (it == lookup_table->end()) ? -1 : 0;

更复杂的解决方案是使用允许读/写锁定的shared_mutex。无论如何,这可能是您想要的,因为您肯定有正在读取查找表的进程?您可以在读取和取消引用 end() 迭代器之前应用读锁。多个线程将能够一次读取数据,但在所有读取器被释放之前不允许写入。

static std::shared_mutex helper_lock;

int helper(int id) 
  static std::map<int,int>* lookup_table = new std::map<int,int>();

  
    std::unique_lock<std::shared_mutex> lock(helper_lock);
    // Modify lookup_table
    // explicit unlock is not required, lock is released when lock is destroyed
  

  // acquire read-only lock, but not if any thread holds a unique_lock
  std::shared_lock<std::shared_mutex> lock(helper_lock);
  return (it == lookup_table->end()) ? -1 : 0;

【讨论】:

以上是关于函数中带有静态变量的竞争条件的主要内容,如果未能解决你的问题,请参考以下文章

新手请教C#中关于静态函数和静态变量

PHP类的静态(static)方法和静态(static)变量使用介绍

在C语言中具体静态变量static要这么去用?

如何在Python中定义静态变量

lua脚本有静态局部变量吗

java基础-变量