Implementing Thread-Safe Data Structures and Avoiding Deadlocks in C++

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();
}

Tags: C++ multithreading mutex deadlock thread-safety

Posted on Sun, 10 May 2026 08:47:50 +0000 by Owe Blomqvist