home | help
std::lock_guard(3)	       C++ Standard Libary	      std::lock_guard(3)

NAME
     std::lock_guard - std::lock_guard

Synopsis
	Defined in header <mutex>
	template< class Mutex >    (since C++11)
	class lock_guard;

	The class lock_guard is a mutex wrapper that provides a convenient RAII-
     style
	mechanism for owning a mutex for the duration of a scoped block.

	When  a  lock_guard  object is created, it attempts to take ownership of
     the mutex it
	is given. When control leaves the scope in which the  lock_guard  object
     was created,
	the lock_guard is destructed and the mutex is released.

	The lock_guard class is non-copyable.

Template parameters
	Mutex - the type of the mutex to lock. The type must meet the BasicLock-
     able
		requirements

Member types
	Member type Definition
	mutex_type  Mutex

Member functions
	constructor    constructs a lock_guard, optionally locking the given mu-
     tex
		      (public member function)
	destructor    destructs the lock_guard object,	unlocks  the  underlying
     mutex
		      (public member function)
	operator=     not copy-assignable
	[deleted]     (public member function)

Notes
	A  common  beginner error is to "forget" to give a lock_guard variable a
     name, e.g.
	std::lock_guard(mtx); (which default constructs  a  lock_guard	variable
     named mtx) or
	std::lock_guard{mtx}; (which constructs a prvalue object that is immedi-
     ately
	destroyed),  thereby not actually constructing a lock that holds a mutex
     for the rest
	of the scope.

	std::scoped_lock offers an alternative for lock_guard that provides
	the  ability  to  lock	multiple  mutexes  using  a  deadlock  avoidance
     (since C++17)
	algorithm.

Example
	Demonstrates  safe  and  unsafe increments of a volatile variable by two
     threads.

     // Run this code

      #include <iostream>
      #include <mutex>
      #include <string_view>
      #include <syncstream>
      #include <thread>

      volatile int g_i = 0;
      std::mutex g_i_mutex;  // protects g_i

      void safe_increment(int iterations)
      {
	  const std::lock_guard<std::mutex> lock(g_i_mutex);
	  while (iterations-- > 0)
	      g_i = g_i + 1;
	  std::cout << "thread #" << std::this_thread::get_id() << ", g_i: "  <<
     g_i << '\n';

	  // g_i_mutex is automatically released when lock goes out of scope
      }

      void unsafe_increment(int iterations)
      {
	  while (iterations-- > 0)
	      g_i = g_i + 1;
	  std::osyncstream(std::cout)	     <<        "thread	     #"       <<
     std::this_thread::get_id()
				      << ", g_i: " << g_i << '\n';
      }

      int main()
      {
	  auto test = [](std::string_view fun_name, auto fun)
	  {
	      g_i = 0;
	      std::cout << fun_name << ":\nbefore, g_i: " << g_i << '\n';
	      {
		  std::jthread t1(fun, 1'000'000);
		  std::jthread t2(fun, 1'000'000);
	      }
	      std::cout << "after, g_i: " << g_i << "\n\n";
	  };
	  test("safe_increment", safe_increment);
	  test("unsafe_increment", unsafe_increment);
      }

Possible output:
      safe_increment:
      before, g_i: 0
      thread #140121493231360, g_i: 1000000
      thread #140121484838656, g_i: 2000000
      after, g_i: 2000000

      unsafe_increment:
      before, g_i: 0
      thread #140121484838656, g_i: 1028945
      thread #140121493231360, g_i: 1034337
      after, g_i: 1034337

	Defect reports

	The following behavior-changing defect	reports  were  applied	retroac-
     tively to
	previously published C++ standards.

	   DR	 Applied to		 Behavior as published		    Cor-
     rect behavior
	LWG  2981 C++17      redundant deduction guide from		     re-
     moved
			    lock_guard<Mutex> was provided

See also
	unique_lock implements movable mutex ownership wrapper
	(C++11)     (class template)
	scoped_lock deadlock-avoiding RAII wrapper for multiple mutexes
	(C++17)     (class template)

http://cppreference.com 	   2024.06.10		      std::lock_guard(3)

home | help