c++++ 多线程同步关键概念:互斥锁:确保临界区只能由一个线程访问。条件变量:线程可在特定条件满足时被唤醒。原子操作:不可中断的单一 cpu 指令,保证共享变量修改的原子性。
C++ 多线程编程的关键概念:线程同步
线程同步是多线程编程中至关重要的一环,它确保多个线程可以安全地访问共享资源,避免竞争和数据损坏。以下介绍 C++ 中实现线程同步的关键概念:
互斥锁:
互斥锁(mutex)是一种访问控制机制,它允许一次只能有一个线程访问临界区,即需要同步访问的代码区域。使用互斥锁可以防止多个线程同时修改共享变量,造成数据损坏。
std::mutex mtx; // 定义互斥锁对象
void someFunction() {
std::lock_guard<std::mutex> lock(mtx); // 在进入临界区前加锁
// 访问临界区代码
}
条件变量:
条件变量允许线程在特定条件满足时被唤醒。这在协作式多线程编程中非常有用,例如当一个线程在等待另一个线程产生数据时。
std::condition_variable cv; // 定义条件变量对象
std::mutex mtx; // 关联的互斥锁对象
void produce() {
std::lock_guard<std::mutex> lock(mtx); // 加锁
// 产生数据
cv.notify_all(); // 通知所有等待此条件的线程
}
void consume() {
std::unique_lock<std::mutex> lock(mtx); // 加锁
cv.wait(lock); // 等待 `produce()` 函数生产数据
// 消费数据
}
原子操作:
原子操作是不可被其他线程中断的单个 CPU 指令,可以确保对共享变量的修改是原子的。
std::atomic<int> count; // 定义原子变量
void incrementCount() {
count++; // 原子方式增加 `count`
}
实战案例:
考虑以下多线程程序:
std::vector<int> numbers; // 共享的整型数组
void addNumber(int n) {
numbers.push_back(n);
}
int main() {
std::thread t1(addNumber, 1);
std::thread t2(addNumber, 2);
t1.join();
t2.join();
std::cout << "Numbers in the vector: ";
for (int n : numbers) {
std::cout << n << " ";
}
std::cout << std::endl;
return 0;
}
在这个例子中,numbers 数组是共享资源,多个线程可以并发访问。如果不采取同步措施,可能会出现竞争条件,导致数据损坏。
为了安全地访问数组,我们可以使用互斥锁:
void addNumber(int n) {
std::lock_guard<std::mutex> lock(mtx); // 在访问数组前加锁
numbers.push_back(n);
}
这样,一次只能有一个线程访问数组,确保数据的完整性。
输出:
Numbers in the vector: 1 2