简体   繁体   中英

Race condition with a static variable in a function

I have the following function:

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 is called in multiple threads. What is the way to prevent a race condition for lookup_table ?

Would this be sufficient?

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

That will NOT be sufficient. Modifications to an STL container have the potential to invalidate its iterators, so the comparison to lookup_table.end() at the end of the function might be invalidated if another thread is modifying the table.

The easy solution is to only unlock after the comparison is done. (note that I'm using std::unique_lock<std::mutex> to do the locking - lock is released when the unique_lock goes out of scope

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

A more complicated solution is to use a shared_mutex that allows a read/write lock. This is likely what you want anyway, since certainly you have processes that are reading the lookup table? You can apply the read-lock before the end() iterator is read and dereferenced. Multiple threads will be able to read the data at once, but none are allowed to write until all readers are released.

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

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM