C ++: is mutex enough with `std :: lock_guard` to synchronize two` std :: thread`?

My question is based on the following C ++ code example

#include <chrono>
#include <thread>
#include <mutex>
#include <iostream>

class ClassUtility
{
public:
    ClassUtility() {}
    ~ClassUtility() {}

    void do_something() {
      std::cout << "do something called" << std::endl;

      using namespace std::chrono_literals;
      std::this_thread::sleep_for(1s);
    }
};


int main (int argc, const char* argv[]) {

  ClassUtility g_common_object;

  std::mutex  g_mutex;

  std::thread worker_thread_1([&](){

      std::cout << "worker_thread_1 started" << std::endl;

      for (;;) {

          std::lock_guard<std::mutex> lock(g_mutex);

          std::cout << "worker_thread_1 looping" << std::endl;
          g_common_object.do_something();
      }
  });


  std::thread worker_thread_2([&](){

      std::cout << "worker_thread_2 started" << std::endl;

      for (;;) {

          std::lock_guard<std::mutex> lock(g_mutex);

          std::cout << "worker_thread_2 looping" << std::endl;
          g_common_object.do_something();
      }
  });


  worker_thread_1.join();
  worker_thread_2.join();

  return 0;
}

It is more a question to understand my understanding and get an example of using std::condition_variableiff required.

I have 2 C ++ std::threadthat run in main. This is a console application on osx. So, compile it using clang. Both threads use a common object ClassUtilityto call a method; perform some heavy task. For this code example, to explain the situation, both threads start an infinite loop and close only when the application closes, that is, when I click ctrl+con the console.

Look for information:

, std::lock_guard std::mutex , common_obejct ClassUtility. - " ". , gaurd . , segfaults. , ? ?

std::condition_variable , ? , std::condition_variable ?

.. , .

+4
2

, lock_guard .lock() .unlock() .

{
    std::lock_guard<std::mutex> lock(g_mutex);
    std::cout << "worker_thread_1 looping" << std::endl;
    g_common_object.do_something();
}

:

{ 
    g_mutex.lock();
    std::cout << "worker_thread_1 looping" << std::endl;
    g_common_object.do_something();
    g_mutex.unlock();
}

  • ,
  • , .

. , . - ( ), .

; std::cout - . :

{ 
    std::cout << "worker_thread_1 looping" << std::endl;
    {
        std::lock_guard<std::mutex> lock(g_mutex);
        g_common_object.do_something();
        // unlocks here, because lock_guard injects unlock at the end of innermost scope.
    }
}

, , , -, ; .

, , , - . , mutex .

+8

, .

, parallelism - , .

, .

, , join()? ( join()) , . .

#include <chrono>
#include <thread>
#include <mutex>
#include <iostream>

class ClassUtility
{
public:
    ClassUtility() {}
    ~ClassUtility() {}

    void do_something() {
      std::cout << "do something called" << std::endl;

      using namespace std::chrono_literals;
      std::this_thread::sleep_for(1s);
    }
};


int main (int argc, const char* argv[]) {

  ClassUtility g_common_object;

  std::mutex  g_mutex;

  std::thread worker_thread_1([&](){

      std::cout << "worker_thread_1 started" << std::endl;

      for (int i=0;i<10;++i) {

          std::lock_guard<std::mutex> lock(g_mutex);

          std::cout << "worker_thread_1 looping " << i << std::endl;
          g_common_object.do_something();
      }
  });


  std::thread worker_thread_2([&](){

      std::cout << "worker_thread_2 started" << std::endl;

      for (int i=0;i<10;++i) {

          std::lock_guard<std::mutex> lock(g_mutex);

          std::cout << "worker_thread_2 looping " << i << std::endl;
          g_common_object.do_something();
      }
  });


  worker_thread_1.join();
  worker_thread_2.join();

  return 0;
}
+1

Source: https://habr.com/ru/post/1674461/


All Articles