在C++中,临界区通常是通过互斥量(mutex)来实现的,因为互斥量用于保护代码段(即临界区),以确保在任意时刻只有一个线程可以执行该代码段。然而,从技术上来说,"临界区"是一个概念,而std::mutex
是实现这一概念的一种手段。
以下是一个使用std::mutex
来保护临界区的C++线程同步应用举例:
#include <iostream>
#include <thread>
#include <mutex>
#include <vector> // 定义一个全局的互斥量
std::mutex mtx; // 共享的全局变量
std::vector<int> data; // 线程函数,用于向共享向量中添加数据
void add_data(int start, int end) { for (int i = start; i < end; ++i) { // 锁定互斥量以保护临界区 std::lock_guard<std::mutex> lock(mtx); // 临界区开始 data.push_back(i); // 临界区结束 // 在这里可以添加一些非关键性的操作,不需要互斥量保护 // ... }
} int main() { const int num_elements = 1000; const int num_threads = 4; const int elements_per_thread = num_elements / num_threads; // 创建线程 std::vector<std::thread> threads; for (int i = 0; i < num_threads; ++i) { int start = i * elements_per_thread; int end = (i == num_threads - 1) ? num_elements : start + elements_per_thread; threads.emplace_back(add_data, start, end); } // 等待所有线程完成 for (auto& t : threads) { t.join(); } // 输出最终数据大小 std::cout << "Final data size is " << data.size() << std::endl; // 理想情况下,最终数据大小应该是1000 return 0;
}
在这个例子中,我们有一个共享的data
向量,多个线程将向其添加数据。为了确保在添加数据时不会发生数据竞争,我们使用了一个std::mutex
来保护向data
添加元素的代码段(即临界区)。每个线程在添加元素之前都会锁定互斥量,添加完成后释放互斥量。这样,在任意时刻只有一个线程能够访问临界区,从而保证了数据的一致性。