- [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;
}