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;
}
相关推荐
虾球xz1 小时前
游戏引擎学习第230天
c++·学习·游戏引擎
不知道叫什么呀3 小时前
【C语言基础】C++ 中的 `vector` 及其 C 语言实现详解
c语言·开发语言·c++
汇太浪3 小时前
第十六届蓝桥杯大赛软件赛省赛 C++ 大学 B 组 部分题解
c++·蓝桥杯
WW_千谷山4_sch4 小时前
MYOJ_11700(UVA10591)Happy Number(快乐数)(超快解法:图论思想解题)
c++·算法
郭涤生4 小时前
QML 信号与槽
c++·笔记·qt
Ethon_王4 小时前
C++ STL deque容器详解
c++
梦の4 小时前
C++Cherno 学习笔记day20 [81]-[85] 可视化基准测试、单例模式、小字符串优化sso、跟踪内存分配、左值与右值
c++·笔记·学习
硬匠的博客5 小时前
C/C++指针
c语言·开发语言·c++
向日葵.5 小时前
CMake学习
开发语言·c++·学习
wuqingshun3141595 小时前
蓝桥杯 1.路径之谜
c++·算法·职场和发展·蓝桥杯·深度优先