c++ - Which part should I lock when dealing with both read and write? -


i'm playing c++(11) stl , got following problem. basic idea code is: have "trigger" function, "add" function , flag(false default). if flag false "add" function's going push threadid queue, otherwise it's going insert threadid set. when trigger function called, set flag "true" , move threadids queue set. initialized 100 threads , use 1 of thread run trigger function(in code it's thread no.30). ideally result should have 0 elements in queue , 99 elements in set. however, result correct, missed numbers in set, , got exc_bad_access error. help? thank you.

#include <iostream> #include <thread> #include <vector> #include <unordered_set> #include <queue> #include <mutex> #include <atomic> using namespace std;   bool flag = false; queue<int> q; unordered_set<int> s; mutex mu;  void trigger() {     mu.lock();     flag = true;     mu.unlock();     while( !q.empty() ){         s.insert(q.front());         q.pop();     } }  void add(int id) {     mu.lock();     if( !flag )          q.push(id);     else {         if ( s.find(id) == s.end() ){             s.insert(id);         }     }     mu.unlock(); }  void missing() {     cout << "missing numbers: ";     (int = 1; <= 100; i++) {         if( s.find(i) == s.end() )              cout << << " ";     }     cout << endl; }  int main() {     vector<thread> threads;      (int = 0; < 100; i++){         if ( == 29 ) threads.push_back(thread(trigger));         else threads.push_back(thread(add, i+1));     }     (int = 0; < 100; i++){         threads[i].join();     }     cout << "q size: " << q.size() << endl;     cout << "s size: " << s.size() << endl;     missing(); } 

you have 1 thread executing trigger function , many threads executing add function. furthermore, take care guard of shared state not of it. see comments/questions in below code snippets.

void trigger() {     // 'flag' protected concurrent acceess     mu.lock();     flag = true;     mu.unlock();      // why isn't 'q' or 's' protected lock?     while( !q.empty() ){         s.insert(q.front());         q.pop();     } }  void add(int id) {     // in function both 'q' , 's' protected concurrent access     mu.lock();     if( !flag )          q.push(id);     else {         if ( s.find(id) == s.end() ){             s.insert(id);         }     }     mu.unlock(); } 

possible solution

in general, should protect state being accessed concurrently. i'd recommend using lock type (e.g., lock_guard) instead of locking , unlocking mutex directly (research raii why encouraged).

#include <iostream> #include <mutex> #include <queue> #include <thread> #include <unordered_set> #include <vector>  using namespace std;  bool flag = false; queue<int> q; unordered_set<int> s; mutex mu;  void trigger() {     lock_guard<mutex> lock(mu);     flag = true;      while (!q.empty())     {         s.insert(q.front());         q.pop();     } }  void add(int id) {     lock_guard<mutex> lock(mu);      if (!flag)     {         q.push(id);     }     else     {         if (s.find(id) == s.end())         {             s.insert(id);         }     } }  void missing() {     cout << "missing numbers: ";     (int = 1; <= 100; ++i)     {         if (s.find(i) == s.end())         {             cout << << " ";         }     }     cout << endl; }  int main() {     vector<thread> threads;     (int = 0; < 100; ++i)     {         if (i == 29)         {             threads.push_back(thread(trigger));         }         else         {             threads.push_back(thread(add, + 1));         }     }      (int = 0; < 100; ++i)     {         threads[i].join();     }      cout << "q size: " << q.size() << endl;     cout << "s size: " << s.size() << endl;     missing();      return 0; } 

Comments

Popular posts from this blog

javascript - AngularJS custom datepicker directive -

javascript - jQuery date picker - Disable dates after the selection from the first date picker -