C++线程同步和互斥

【欢迎关注编码小哥,学习更多实用的编程方法和技巧】

1、互斥锁基本使用

cpp 复制代码
#include <mutex>
#include <thread>
#include <iostream>

class Counter {
private:
    int value = 0;
    std::mutex mtx;

public:
    // 使用互斥锁保护临界区
    void increment() {
        // 传统加锁方式
        mtx.lock();
        value++;
        mtx.unlock();
    }

    // 推荐使用RAII锁
    void incrementSafe() {
        std::lock_guard<std::mutex> lock(mtx);
        value++;
    }

    int getValue() {
        std::lock_guard<std::mutex> lock(mtx);
        return value;
    }
};

2、 读写锁

cpp 复制代码
#include <shared_mutex>

class ThreadSafeCache {
private:
    std::unordered_map<int, std::string> cache;
    mutable std::shared_mutex mtx;

public:
    // 写操作
    void put(int key, const std::string& value) {
        std::unique_lock<std::shared_mutex> lock(mtx);
        cache[key] = value;
    }

    // 读操作
    std::string get(int key) const {
        std::shared_lock<std::shared_mutex> lock(mtx);
        auto it = cache.find(key);
        return (it != cache.end()) ? it->second : "";
    }
};

3、 条件变量

cpp 复制代码
#include <condition_variable>
#include <queue>

class ThreadSafeQueue {
private:
    std::queue<int> queue;
    std::mutex mtx;
    std::condition_variable cv;

public:
    void push(int value) {
        {
            std::lock_guard<std::mutex> lock(mtx);
            queue.push(value);
        }
        cv.notify_one(); // 通知等待线程
    }

    int pop() {
        std::unique_lock<std::mutex> lock(mtx);
        
        // 等待直到队列非空
        cv.wait(lock, [this]() { 
            return !queue.empty(); 
        });

        int value = queue.front();
        queue.pop();
        return value;
    }
};

4、原子操作

cpp 复制代码
#include <atomic>

class AtomicCounter {
private:
    std::atomic<int> counter{0};

public:
    void increment() {
        // 原子自增
        counter++;
    }

    int get() {
        return counter.load(); // 原子读取
    }

    // 复杂原子操作
    void complexOperation() {
        counter.compare_exchange_weak(
            expected,  // 期望值
            desired    // 新值
        );
    }
};

5、死锁预防

cpp 复制代码
class DeadlockPrevention {
private:
    std::mutex mtx1, mtx2;

public:
    void safeOperation() {
        // 使用std::lock避免死锁
        std::lock(mtx1, mtx2);
        
        // RAII锁
        std::lock_guard<std::mutex> lock1(mtx1, std::adopt_lock);
        std::lock_guard<std::mutex> lock2(mtx2, std::adopt_lock);

        // 临界区代码
    }
};

6、信号量

cpp 复制代码
class Semaphore {
private:
    std::mutex mtx;
    std::condition_variable cv;
    int count;

public:
    explicit Semaphore(int initial = 0) : count(initial) {}

    void wait() {
        std::unique_lock<std::mutex> lock(mtx);
        cv.wait(lock, [this] { return count > 0; });
        --count;
    }

    void signal() {
        std::unique_lock<std::mutex> lock(mtx);
        ++count;
        cv.notify_one();
    }
};

7、生产者、消费者模型

cpp 复制代码
class ProducerConsumer {
private:
    std::queue<int> queue;
    std::mutex mtx;
    std::condition_variable not_full;
    std::condition_variable not_empty;
    const size_t CAPACITY = 10;

public:
    void produce(int value) {
        std::unique_lock<std::mutex> lock(mtx);
        
        // 等待队列不满
        not_full.wait(lock, [this]{ 
            return queue.size() < CAPACITY; 
        });

        queue.push(value);
        lock.unlock();
        not_empty.notify_one();
    }

    int consume() {
        std::unique_lock<std::mutex> lock(mtx);
        
        // 等待队列非空
        not_empty.wait(lock, [this]{ 
            return !queue.empty(); 
        });

        int value = queue.front();
        queue.pop();
        lock.unlock();
        not_full.notify_one();

        return value;
    }
};

8、性能优化

cpp 复制代码
// 减少锁的粒度
class OptimizedCounter {
private:
    // 使用更细粒度的锁
    std::array<std::mutex, 16> locks;
    std::array<int, 16> counters = {0};

public:
    void increment(int index) {
        // 根据索引选择特定锁
        std::lock_guard<std::mutex> lock(locks[index % locks.size()]);
        counters[index % counters.size()]++;
    }
};

9、同步原语选择建议

  • 互斥锁:简单的临界区保护
  • 读写锁:读多写少场景
  • 条件变量:线程间通信
  • 原子操作:简单共享变量
  • 信号量:资源受限场景

关键原则:

  • 最小化锁的持有时间
  • 避免嵌套锁
  • 使用RAII管理锁
  • 选择合适的同步原语
  • 注意性能开销
相关推荐
我材不敲代码3 小时前
Python实现打包贪吃蛇游戏
开发语言·python·游戏
身如柳絮随风扬4 小时前
Java中的CAS机制详解
java·开发语言
-dzk-6 小时前
【代码随想录】LC 59.螺旋矩阵 II
c++·线性代数·算法·矩阵·模拟
韩立学长6 小时前
【开题答辩实录分享】以《基于Python的大学超市仓储信息管理系统的设计与实现》为例进行选题答辩实录分享
开发语言·python
froginwe116 小时前
Scala 循环
开发语言
m0_706653236 小时前
C++编译期数组操作
开发语言·c++·算法
故事和你917 小时前
sdut-Java面向对象-06 继承和多态、抽象类和接口(函数题:10-18题)
java·开发语言·算法·面向对象·基础语法·继承和多态·抽象类和接口
Bruk.Liu7 小时前
(LangChain实战2):LangChain消息(message)的使用
开发语言·langchain
qq_423233907 小时前
C++与Python混合编程实战
开发语言·c++·算法
m0_715575347 小时前
分布式任务调度系统
开发语言·c++·算法