lock
(C++)
Locks are a synchronization technique used to limit access to a resource in an environment where there are many threads of execution. A good example of a lock is a Mutex.
Resources
std::mutex foo,bar;
void task_a () {
// foo.lock(); bar.lock(); // replaced by:
std::lock (foo,bar);
std::cout << "task a\n";
foo.unlock();
bar.unlock();
}
void task_b () {
// bar.lock(); foo.lock(); // replaced by:
std::lock (bar,foo);
std::cout << "task b\n";
bar.unlock();
foo.unlock();
}
int main ()
{
std::thread th1 (task_a);
std::thread th2 (task_b);
th1.join();
th2.join();
return 0;
}
Cool types of locks
shared_lock
shared_lock
allows deferred locking, timed locking and transfer of lock ownership.
https://en.cppreference.com/w/cpp/thread/shared_lock/shared_lock
#include <shared_mutex>
#include <syncstream>
#include <iostream>
#include <thread>
#include <chrono>
std::shared_timed_mutex m;
int i = 10;
void read_shared_var(int id)
{
// both the threads get access to the integer i
std::shared_lock<std::shared_timed_mutex> slk(m);
const int ii = i; // reads global i
std::osyncstream(std::cout) << "#" << id << " read i as " << ii << "...\n";
std::this_thread::sleep_for(std::chrono::milliseconds(10));
std::osyncstream(std::cout) << "#" << id << " woke up..." << std::endl;
}
int main()
{
std::thread r1 {read_shared_var, 1};
std::thread r2 {read_shared_var, 2};
r1.join();
r2.join();
}
unique_lock
unique_lock
locks in exclusive mode.
https://en.cppreference.com/w/cpp/thread/unique_lock
https://stackoverflow.com/questions/14709233/how-to-use-create-unique-lock-in-c
#include <mutex>
#include <thread>
#include <iostream>
struct Box
{
explicit Box(int num) : num_things{num} {}
int num_things;
std::mutex m;
};
void transfer(Box &from, Box &to, int num)
{
// don't actually take the locks yet
std::unique_lock lock1{from.m, std::defer_lock};
std::unique_lock lock2{to.m, std::defer_lock};
// lock both unique_locks without deadlock
std::lock(lock1, lock2);
from.num_things -= num;
to.num_things += num;
// 'from.m' and 'to.m' mutexes unlocked in 'unique_lock' dtors
}
int main()
{
Box acc1{100};
Box acc2{50};
std::thread t1{transfer, std::ref(acc1), std::ref(acc2), 10};
std::thread t2{transfer, std::ref(acc2), std::ref(acc1), 5};
t1.join();
t2.join();
std::cout << "acc1: " << acc1.num_things << "\n"
"acc2: " << acc2.num_things << '\n';
}