- 使用
std::mutex
和std::unique_lock
实现安全访问
- 首先定义一个
std::mutex
对象,用于保护std::vector<int>
容器。
- 在对
std::vector<int>
进行访问或修改的函数中,使用std::unique_lock<std::mutex>
来锁定std::mutex
。std::unique_lock
提供了更灵活的锁管理方式,比如可以在构造时锁定,在析构时自动解锁。
示例代码如下:
#include <iostream>
#include <vector>
#include <mutex>
#include <thread>
std::vector<int> sharedVector;
std::mutex vectorMutex;
void addElement(int num) {
std::unique_lock<std::mutex> lock(vectorMutex);
sharedVector.push_back(num);
}
void printVector() {
std::unique_lock<std::mutex> lock(vectorMutex);
for (int num : sharedVector) {
std::cout << num << " ";
}
std::cout << std::endl;
}
int main() {
std::thread t1(addElement, 1);
std::thread t2(addElement, 2);
std::thread t3(printVector);
t1.join();
t2.join();
t3.join();
return 0;
}
- 优化方案
- 减少锁的粒度:
- 如果
std::vector<int>
容器中的操作可以被细分为独立的部分,那么可以对不同部分使用不同的锁。例如,如果只是对std::vector<int>
的前半部分和后半部分分别进行独立操作,可以定义两个std::mutex
,一个保护前半部分,一个保护后半部分。这样不同线程就可以同时操作不同部分,提高并发性能。
- 读写锁:
- 如果对
std::vector<int>
的操作读多写少,可以使用读写锁(如std::shared_mutex
)。读操作可以同时进行,只有写操作需要独占锁。在C++ 17及以上,std::shared_mutex
可以和std::unique_lock
(通过指定合适的锁策略,如std::defer_lock
等)以及std::shared_lock
配合使用。例如:
#include <iostream>
#include <vector>
#include <shared_mutex>
#include <thread>
std::vector<int> sharedVector;
std::shared_mutex vectorMutex;
void readElement() {
std::shared_lock<std::shared_mutex> lock(vectorMutex);
// 进行读操作
for (int num : sharedVector) {
std::cout << num << " ";
}
std::cout << std::endl;
}
void writeElement(int num) {
std::unique_lock<std::shared_mutex> lock(vectorMutex);
// 进行写操作
sharedVector.push_back(num);
}
- 无锁数据结构:
- 考虑使用无锁数据结构来替代
std::vector<int>
,如std::atomic
相关的数据结构或者一些第三方的无锁数据结构库。无锁数据结构通过使用原子操作避免了锁带来的性能开销,但实现和使用通常更复杂。例如,在某些场景下,可以使用std::atomic<int>
数组来模拟类似std::vector<int>
的功能。