Basic Mutex Usage
#include <iostream>
#include <mutex>
#include <thread>
int shared_counter = 0;
std::mutex counter_mutex;
void increment_counter()
{
for(int i = 0; i < 10; ++i) {
std::lock_guard<std::mutex> guard(counter_mutex);
++shared_counter;
std::cout << "Thread " << std::this_thread::get_id()
<< " counter: " << shared_counter << std::endl;
std::this_thread::sleep_for(std::chrono::microseconds(10));
}
}
void decrement_counter()
{
for(int i = 0; i < 10; ++i) {
counter_mutex.lock();
--shared_counter;
std::cout << "Thread " << std::this_thread::get_id()
<< " counter: " << shared_counter << std::endl;
counter_mutex.unlock();
std::this_thread::sleep_for(std::chrono::microseconds(10));
}
}
void demonstrate_mutex()
{
std::thread t1(increment_counter);
std::thread t2(decrement_counter);
t1.join();
t2.join();
}
int main()
{
demonstrate_mutex();
return 0;
}
Thread-Safe Stack Implemantation
#include <exception>
#include <memory>
#include <stack>
#include <mutex>
struct stack_empty_exception : std::exception
{
const char* what() const noexcept override { return "Stack is empty"; }
};
template<typename T>
class ThreadSafeStack
{
private:
std::stack<T> stack_data;
mutable std::mutex stack_mutex;
public:
ThreadSafeStack() = default;
ThreadSafeStack(const ThreadSafeStack& other)
{
std::lock_guard<std::mutex> lock(other.stack_mutex);
stack_data = other.stack_data;
}
ThreadSafeStack& operator=(const ThreadSafeStack&) = delete;
void push(T value)
{
std::lock_guard<std::mutex> lock(stack_mutex);
stack_data.push(std::move(value));
}
std::shared_ptr<T> pop()
{
std::lock_guard<std::mutex> lock(stack_mutex);
if(stack_data.empty()) throw stack_empty_exception();
std::shared_ptr<T> result(std::make_shared<T>(stack_data.top()));
stack_data.pop();
return result;
}
void pop(T& value)
{
std::lock_guard<std::mutex> lock(stack_mutex);
if(stack_data.empty()) throw stack_empty_exception();
value = stack_data.top();
stack_data.pop();
}
bool empty() const
{
std::lock_guard<std::mutex> lock(stack_mutex);
return stack_data.empty();
}
};
Deadlock Prevention Strategies
#include <mutex>
std::mutex primary_lock;
std::mutex secondary_lock;
int primary_data, secondary_data;
void safe_operation_1()
{
std::lock(primary_lock, secondary_lock);
std::lock_guard<std::mutex> lock1(primary_lock, std::adopt_lock);
std::lock_guard<std::mutex> lock2(secondary_lock, std::adopt_lock);
primary_data = 100;
secondary_data = 200;
}
void safe_operation_2()
{
std::lock(secondary_lock, primary_lock);
std::lock_guard<std::mutex> lock1(secondary_lock, std::adopt_lock);
std::lock_guard<std::mutex> lock2(primary_lock, std::adopt_lock);
primary_data = 300;
secondary_data = 400;
}
Hierarchical Mutex Implementation
#include <mutex>
#include <stdexcept>
#include <climits>
class HierarchicalMutex
{
private:
std::mutex internal_mutex;
const unsigned long hierarchy_level;
unsigned long previous_level;
static thread_local unsigned long current_thread_level;
void validate_hierarchy()
{
if(current_thread_level <= hierarchy_level) {
throw std::logic_error("Hierarchy violation detected");
}
}
void update_hierarchy()
{
previous_level = current_thread_level;
current_thread_level = hierarchy_level;
}
public:
explicit HierarchicalMutex(unsigned long level)
: hierarchy_level(level), previous_level(0) {}
void lock()
{
validate_hierarchy();
internal_mutex.lock();
update_hierarchy();
}
void unlock()
{
if(current_thread_level != hierarchy_level) {
throw std::logic_error("Hierarchy mismatch on unlock");
}
current_thread_level = previous_level;
internal_mutex.unlock();
}
bool try_lock()
{
validate_hierarchy();
if(!internal_mutex.try_lock()) return false;
update_hierarchy();
return true;
}
};
thread_local unsigned long HierarchicalMutex::current_thread_level = ULONG_MAX;
void demonstrate_hierarchy()
{
HierarchicalMutex high_level(1000);
HierarchicalMutex low_level(500);
std::thread([&high_level, &low_level]() {
high_level.lock(); // OK: current level = ULONG_MAX > 1000
low_level.lock(); // OK: current level = 1000 > 500
low_level.unlock();
high_level.unlock();
}).join();
}