C++ 线程 一些同步方式

  • [C++ 线程](#C++ 线程)
  • 一些同步方式
    • 1.互斥锁(Mutex)
    • [2. 读写锁(Reader-Writer Lock)](#2. 读写锁(Reader-Writer Lock))
    • [3. 信号量(Semaphore)](#3. 信号量(Semaphore))
    • [4. 原子操作(Atomic)](#4. 原子操作(Atomic))
    • [5. 屏障(Barrier)](#5. 屏障(Barrier))
    • [6. 条件变量(Condition Variable)](#6. 条件变量(Condition Variable))

一些同步方式

在多线程编程中,除了条件变量(condition variable)之外,还有其他几种常见的同步机制,每种机制都有其特定的使用场景和优势。以下是一些常见的同步方式:

1.互斥锁(Mutex)

互斥锁是最基本的同步机制,用于保护共享数据,防止多个线程同时访问导致数据竞争。

示例代码:

c++ 复制代码
#include <iostream>
#include <thread>
#include <mutex>

// 声明一个互斥锁对象
std::mutex mtx;

// 声明一个共享数据变量,初始值为0
int shared_data = 0;

// 线程函数:增加共享数据的值
void increment() {
    // 使用lock_guard锁定互斥锁,确保线程安全
    std::lock_guard<std::mutex> lock(mtx);
    
    // 增加共享数据的值
    shared_data++;
}

int main() {
    // 创建两个线程,每个线程调用increment函数
    std::thread t1(increment);
    std::thread t2(increment);
    
    // 等待两个线程完成
    t1.join();
    t2.join();
    
    // 输出共享数据的最终值
    std::cout << "Shared data: " << shared_data << std::endl;
    
    // 返回0,表示程序正常结束
    return 0;
}

2. 读写锁(Reader-Writer Lock)

读写锁允许多个读线程同时访问共享数据,但写线程独占访问。适用于读多写少的场景。

示例代码:

c++ 复制代码
#include <iostream>
#include <thread>
#include <shared_mutex>

// 声明一个读写锁对象
std::shared_mutex rw_mtx;

// 声明一个共享数据变量,初始值为0
int shared_data = 0;

// 读线程函数:读取共享数据的值
void read() {
    // 使用shared_lock锁定读写锁,允许多个读线程同时访问
    std::shared_lock<std::shared_mutex> lock(rw_mtx);
    
    // 输出读取到的共享数据的值
    std::cout << "Read data: " << shared_data << std::endl;
}

// 写线程函数:增加共享数据的值
void write() {
    // 使用unique_lock锁定读写锁,独占访问,阻止其他读写线程
    std::unique_lock<std::shared_mutex> lock(rw_mtx);
    
    // 增加共享数据的值
    shared_data++;
    
    // 输出写入后的共享数据的值
    std::cout << "Write data: " << shared_data << std::endl;
}

int main() {
    // 创建一个读线程和一个写线程
    std::thread t1(read);
    std::thread t2(write);
    
    // 等待两个线程完成
    t1.join();
    t2.join();
    
    // 返回0,表示程序正常结束
    return 0;
}

3. 信号量(Semaphore)

信号量用于控制对共享资源的访问,可以用于线程间的同步和互斥。

示例代码:

c++ 复制代码
#include <iostream>
#include <thread>
#include <semaphore>

// 声明一个计数信号量对象,初始值为1
std::counting_semaphore<1> sem(1);

// 声明一个共享数据变量,初始值为0
int shared_data = 0;

// 线程函数:增加共享数据的值
void increment() {
    // 获取信号量,阻塞直到信号量可用
    sem.acquire();
    
    // 增加共享数据的值
    shared_data++;
    
    // 释放信号量,允许其他线程获取
    sem.release();
}

int main() {
    // 创建两个线程,每个线程调用increment函数
    std::thread t1(increment);
    std::thread t2(increment);
    
    // 等待两个线程完成
    t1.join();
    t2.join();
    
    // 输出共享数据的最终值
    std::cout << "Shared data: " << shared_data << std::endl;
    
    // 返回0,表示程序正常结束
    return 0;
}

4. 原子操作(Atomic)

原子操作提供了一种无锁的同步机制,适用于对单个变量的简单操作。

示例代码:

c++ 复制代码
#include <iostream>
#include <thread>
#include <atomic>

// 声明一个原子整数变量,初始值为0
std::atomic<int> shared_data(0);

// 线程函数:增加共享数据的值
void increment() {
    // 使用原子操作增加共享数据的值
    shared_data++;
}

int main() {
    // 创建两个线程,每个线程调用increment函数
    std::thread t1(increment);
    std::thread t2(increment);
    
    // 等待两个线程完成
    t1.join();
    t2.join();
    
    // 输出共享数据的最终值
    std::cout << "Shared data: " << shared_data << std::endl;
    
    // 返回0,表示程序正常结束
    return 0;
}

5. 屏障(Barrier)

c++ 复制代码
#include <iostream>
#include <thread>
#include <barrier>

// 声明一个屏障对象,初始计数为3
std::barrier bar(3);

// 工作线程函数:模拟工作并使用屏障进行同步
void worker() {
    // 输出工作线程开始的信息
    std::cout << "Worker started" << std::endl;
    
    // 到达屏障并等待,直到所有线程都到达屏障
    bar.arrive_and_wait();
    
    // 输出工作线程结束的信息
    std::cout << "Worker finished" << std::endl;
}

int main() {
    // 创建三个线程,每个线程调用worker函数
    std::thread t1(worker);
    std::thread t2(worker);
    std::thread t3(worker);
    
    // 等待三个线程完成
    t1.join();
    t2.join();
    t3.join();
    
    // 返回0,表示程序正常结束
    return 0;
}

6. 条件变量(Condition Variable)

条件变量用于在一个线程等待某个条件成立时挂起该线程,并在条件成立时通知该线程继续执行。

示例代码:

c++ 复制代码
#include <iostream>
#include <thread>
#include <mutex>
#include <condition_variable>

// 声明一个互斥锁对象
std::mutex mtx;

// 声明一个条件变量对象
std::condition_variable cv;

// 声明一个布尔变量,用于表示条件是否成立
bool ready = false;

// 工作线程函数:等待条件成立并开始工作
void worker() {
    // 使用unique_lock锁定互斥锁
    std::unique_lock<std::mutex> lock(mtx);
    
    // 等待条件变量,直到ready为true
    cv.wait(lock, []{ return ready; });
    
    // 输出工作线程开始的信息
    std::cout << "Worker started" << std::endl;
}

// 触发线程函数:设置条件并通知等待的线程
void trigger() {
    // 使用lock_guard锁定互斥锁
    std::lock_guard<std::mutex> lock(mtx);
    
    // 设置ready为true,表示条件成立
    ready = true;
    
    // 通知一个等待的线程
    cv.notify_one();
}

int main() {
    // 创建一个工作线程和一个触发线程
    std::thread t1(worker);
    std::thread t2(trigger);
    
    // 等待两个线程完成
    t1.join();
    t2.join();
    
    // 返回0,表示程序正常结束
    return 0;
}
相关推荐
螺旋天光极锐斩空闪壹式!1 分钟前
自制游戏:监狱逃亡
c++·游戏
工业3D_大熊1 小时前
3D可视化引擎HOOPS Luminate场景图详解:形状的创建、销毁与管理
java·c++·3d·docker·c#·制造·数据可视化
暮色_年华1 小时前
Modern Effective C++ Item 11:优先考虑使用deleted函数而非使用未定义的私有声明
c++
流星白龙1 小时前
【C++习题】10.反转字符串中的单词 lll
开发语言·c++
Smile丶凉轩1 小时前
微服务即时通讯系统的实现(服务端)----(1)
c++·git·微服务·github
萝卜兽编程2 小时前
优先级队列
c++·算法
珹洺3 小时前
C语言数据结构——详细讲解 双链表
c语言·开发语言·网络·数据结构·c++·算法·leetcode
孙同学要努力3 小时前
C++知识整理day1——前置基础知识整理(命名空间、输入输出、函数重载、引用)
开发语言·c++
沐泽Mu3 小时前
嵌入式学习-C嘎嘎-Day05
开发语言·c++·学习
几窗花鸢4 小时前
力扣面试经典 150(下)
数据结构·c++·算法·leetcode