在看ORB-SLAM代码的时候,经常会遇到unique_lock<mutex>
这种代码,这是C++中多线程编程中线程独占锁的概念,本篇博客主要对其进行简单学习。
1.CMake文件需要增加的内容
在CMake文件中需要设置一下CMake的FLAG,具体来说是pthread
。一个完整CMake文件写法如下,以供参考:
cmake_minimum_required(VERSION 3.15)
project(learnThread)
set(CMAKE_CXX_STANDARD 11)
# 增加FLAG以启用多线程功能
#set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -pthread")
# 如果需要调试再加几个参数
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall -pthread -g -march=native")
# 由于会生成多个可执行文件,所以就添加了多个
add_executable(demo1 demo1.cpp)
add_executable(demo2 demo2.cpp)
2.最简单的线程使用
要使用多线程,最基本需要包含thread.h
头文件。新建线程并运行的最简单方法如下所示:
#include <iostream>
#include <unistd.h> // Linux系统下的头文件,下面用到的sleep函数就是出自这里,其本身与多线程没什么关系
#include <thread> // C++多线程API头文件
using namespace std;
// 不带参数的线程函数
void demo1_thread1() {
while (true) {
sleep(1);
cout << "hello world" << endl;
}
}
// 传入参数的线程函数
void demo1_thread2(int n) {
while (true) {
sleep(1);
cout << "input parameter " << n << endl;
}
}
int main() {
int a = 1;
// 新建两个thread对象
thread t1(&demo1_thread1); // 不带参数
thread t2(&demo1_thread2, a); // 带参数
// 调用thread对象的成员函数join实现运行
t1.join();
t2.join();
return 0;
}
3.线程同步锁unique_lock的使用
在多线程中经常会遇到多个线程同时修改同一个变量的情况,这个时候如果不对线程进行一定约束,很可能会导致意想不到的结果。例如有两个线程1和线程2,线程2的输入是线程1的结果。很显然如果在主线程中同时开启了线程1和线程2,像上面那样,它们是同时运行的,会直接导致程序的崩溃。所以线程同步锁应运而生,当遇到它时它会让当前线程独占某个变量,其它同样需要修改该变量的线程此时只能处于等待状态,等到当前线程结束之后,线程独占锁自动释放,其它线程可以修改内容。示例如下。
#include <iostream>
#include <unistd.h> // Linux系统下的头文件,下面用到的sleep函数就是出自这里,其本身与多线程没什么关系
#include <thread> // C++多线程API头文件
#include <mutex>
#include <vector>
using namespace std;
vector<int> vec_int;
// mutex类型的独占锁
std::mutex mymutex;
void demo2_thread1() {
// 在线程函数执行前加上这一句
unique_lock<mutex> lock(mymutex);
for (int i = 0; i < 5; ++i) {
cout << "Adding element " << i << " from thread 1" << endl;
vec_int.push_back(i);
sleep(1);
}
}
void demo2_thread2() {
// 在线程函数执行前加上这一句
unique_lock<mutex> lock(mymutex);
for (int i = 0; i < 5; ++i) {
int e = 100 * i + 100;
cout << "Adding element " << e << " from thread 2" << endl;
vec_int.push_back(e);
sleep(1);
}
}
int main() {
thread t1(&demo2_thread1);
thread t2(&demo2_thread2);
t1.join();
t2.join();
for (size_t i = 0; i < vec_int.size(); ++i) {
cout << "element " << i << " " << vec_int[i] << endl;
}
return 0;
}
上面程序的两个线程分别向同一个vector
中添加元素,如果没有线程独占锁的保障,会导致添加的元素是乱序的。增加了独占锁以后,输出结果如下。
同时,作为对比,没有添加独占锁的运行结果如下:
可以看到元素是乱序的。
所有示例代码放到了Github上,点击查看。
4.参考资料
- [1]https://blog.csdn.net/coolwriter/article/details/79883253
本文作者原创,未经许可不得转载,谢谢配合