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;
}
相关推荐
DARLING Zero two♡40 分钟前
【优选算法】Sliding-Chakra:滑动窗口的算法流(上)
java·开发语言·数据结构·c++·算法
hjxxlsx43 分钟前
二维数组综合
c++·算法
小王努力学编程1 小时前
【C++篇】AVL树的实现
java·开发语言·c++
yuanbenshidiaos1 小时前
C++-----图
开发语言·c++·算法
就一枚小白1 小时前
UE--如何用 Python 调用 C++ 及蓝图函数
c++·python·ue5
✿ ༺ ོIT技术༻2 小时前
同步&异步日志系统:设计模式
linux·c++·设计模式
獨枭8 小时前
CMake 构建项目并整理头文件和库文件
c++·github·cmake
小王爱吃月亮糖9 小时前
C++的23种设计模式
开发语言·c++·qt·算法·设计模式·ecmascript
小哈龙11 小时前
c++ 类似与c# 线程 AutoResetEvent 和 ManualResetEvent的实现
c++·c#·多线程
yuanbenshidiaos11 小时前
C++--------------树
java·数据库·c++