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;
}
相关推荐
lulu_gh_yu1 小时前
数据结构之排序补充
c语言·开发语言·数据结构·c++·学习·算法·排序算法
ULTRA??1 小时前
C加加中的结构化绑定(解包,折叠展开)
开发语言·c++
凌云行者2 小时前
OpenGL入门005——使用Shader类管理着色器
c++·cmake·opengl
凌云行者2 小时前
OpenGL入门006——着色器在纹理混合中的应用
c++·cmake·opengl
~yY…s<#>2 小时前
【刷题17】最小栈、栈的压入弹出、逆波兰表达式
c语言·数据结构·c++·算法·leetcode
可均可可3 小时前
C++之OpenCV入门到提高004:Mat 对象的使用
c++·opencv·mat·imread·imwrite
白子寰3 小时前
【C++打怪之路Lv14】- “多态“篇
开发语言·c++
小芒果_014 小时前
P11229 [CSP-J 2024] 小木棍
c++·算法·信息学奥赛
gkdpjj4 小时前
C++优选算法十 哈希表
c++·算法·散列表
王俊山IT4 小时前
C++学习笔记----10、模块、头文件及各种主题(一)---- 模块(5)
开发语言·c++·笔记·学习