Этого будет недостаточно. Модификации контейнера STL потенциально могут сделать недействительными его итераторы, поэтому сравнение с lookup_table.end()
в конце функции может быть недействительным, если другой поток модифицирует таблицу.
Простое решение - разблокировать только после того, как сравнение сделано. (обратите внимание, что я использую std::unique_lock<std::mutex>
для выполнения блокировки - блокировка снимается, когда 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;
}