Sharing data with another thread using lock_guard I wrote a updater_thread() and a reader_thread(), and used lock_guard to protect a global instance.
Question

I've never used lock_guard. In this code, is lock_guard used properly?

Is this code thread-safe?


Code
#include &lt;iostream&gt;
#include &lt;thread&gt;
#include &lt;mutex&gt;
#include &lt;iterator&gt;
#include &lt;algorithm&gt;
#include &lt;vector&gt;
#include &lt;initializer_list&gt;
#include &lt;unistd.h&gt;

class C {
  std::vector&lt;int&gt; v;
  std::mutex mutex_;

public:
  C() {}
  void Update(const std::vector&lt;int&gt; &amp;new_v) {
    std::lock_guard&lt;std::mutex&gt; lock(mutex_);
    v = new_v;
  }
  bool Check(const int x){
    std::lock_guard&lt;std::mutex&gt; lock(mutex_);
    return std::find(v.begin(), v.end(), x) != v.end();
  }
  /* dump() is not essential */
  void dump() {
    std::lock_guard&lt;std::mutex&gt; lock(mutex_);
    std::cout &lt;&lt; &quot;dump: &quot;;
    std::copy(v.begin(), v.end(),
              std::ostream_iterator&lt;int&gt;(std::cout, &quot; &quot;));
    std::cout &lt;&lt; &quot;\n&quot;;
  }
};

// create an instance gloablly
C g_c;

void updater_thread() {
  std::cout &lt;&lt; &quot;start updater_thread\n&quot;;
  while (true) {
    std::vector&lt;int&gt; v;
    for (int i = 0; i &lt; 10; i++) {
        v.push_back(rand() % 10 + 1);
    }
    std::sort(v.begin(), v.end());
    g_c.Update(v);
    std::cout &lt;&lt; &quot;updated!!!\n&quot;;
    std::copy(v.begin(), v.end(),
              std::ostream_iterator&lt;int&gt;(std::cout, &quot; &quot;));
    std::cout &lt;&lt; &quot;\n&quot;;
    sleep(5);
  }
}

void reader_thread() {
  std::vector&lt;int&gt; v {1,2,3,5};
  while (true) {
    std::cout &lt;&lt; &quot;check: non-exist item: &quot;;
    for (int i = 0; i &lt; v.size(); i++) {
        if (!g_c.Check(v[i])){
            std::cout &lt;&lt;  v[i] &lt;&lt; &quot; &quot;;
        }
    }
    std::cout &lt;&lt; &quot;\n&quot;;
    sleep(1);
  }
}

int main() {
  std::thread t_up(updater_thread);
  std::thread t_r(reader_thread);
  t_up.join();
  t_r.join();
}
Yes, that all looks correct to me!

You don't use anything from &lt;unistd.h&gt; (non-standard) or &lt;initializer_list&gt; (obscure), so I recommend removing those includes.



You sigil the mutex_ data member with an underscore, but you don't sigil the v member. I recommend being consistent:

std::mutex mutex_;
std::vector&lt;int&gt; v_;


Personally I would spell the member's name mtx_, but that's just a personal habit; I don't know if that naming convention is widespread. (cv_ for a condition variable certainly is, though!)



Consider that your Check and dump methods don't need to mutate the object, so they should be declared const. This means that your mutex_ data member will need to be declared mutable so that you can still lock and unlock it inside your const member functions.

Also, consider picking a capitalization rule and sticking to it. Why Check and Update but dump (not Dump)?

Check's parameter x is marked const but that marking serves no purpose: eliminate it. (Const is a contract.)



for (int i = 0; i &lt; v.size(); i++) {
    if (!g_c.Check(v[i])){
        std::cout &lt;&lt;  v[i] &lt;&lt; " ";
    }
}


This could be rewritten more concisely as

for (int vi : v) {
    if (!g_c.Check(vi)) {
        std::cout &lt;&lt; vi &lt;&lt; " ";
    }
}


Your multithreading stuff all looks great!