c++学习笔记(四)- 多线程 互斥 cmake

c++ mutex

std::mutex 的成员函数

  • 构造函数,std::mutex不允许拷贝构造,也不允许 move 拷贝,最初产生的 mutex 对象是处于 unlocked 状态的。
  • lock(),调用线程将锁住该互斥量。线程调用该函数会发生下面 3 种情况:(1). 如果该互斥量当前没有被锁住,则调用线程将该互斥量锁住,直到调用 unlock之前,该线程一直拥有该锁。(2). 如果当前互斥量被其他线程锁住,则当前的调用线程被阻塞住。(3). 如果当前互斥量被当前调用线程锁住,则会产生死锁(deadlock)。
  • unlock(), 解锁,释放对互斥量的所有权。
  • try_lock(),尝试锁住互斥量,如果互斥量被其他线程占有,则当前线程也不会被阻塞。线程调用该函数也会出现下面 3 种情况,(1). 如果当前互斥量没有被其他线程占有,则该线程锁住互斥量,直到该线程调用 unlock 释放互斥量。(2). 如果当前互斥量被其他线程锁住,则当前调用线程返回 false,而并不会被阻塞掉。(3). 如果当前互斥量被当前调用线程锁住,则会产生死锁(deadlock)。

用到了c++11规范里的多线程,然后编译的时候就报错了,中午各种改CMakeLists没搞定,下午师弟介绍文档,cmake practice,参考第七章,搞定了。

只需要CMakeLists.txt里添加一句话:

set(CMAKE_CXX_FLAGS ${CMAKE_CXX_FLAGS} "-std=c++11 -pthread")

开始的时候没有-pthread能make,但运行的时候就崩溃了,参考这里解决。

根据讨论,桌面Linux环境这样就行了,如果是嵌入式交叉编译环境的话,还需要显示添加

find_package (Threads)

万一以后要写树莓派呢~

存疑:

中午试的不成功的CMakeLists是从已经编译通过的ORB_SLAM2里拿过来的,如下,当时编译没有问题,且运行tum_mono,cpu使用率从低于100%到最后能高于200%,应该3个线程都开了才会占用这么多吧,不太清楚为什么拿到自己的工程里不行。

 1 # Check C++11 or C++0x support
 2 include(CheckCXXCompilerFlag)
 3 CHECK_CXX_COMPILER_FLAG("-std=c++11" COMPILER_SUPPORTS_CXX11)
 4 CHECK_CXX_COMPILER_FLAG("-std=c++0x" COMPILER_SUPPORTS_CXX0X)
 5 if(COMPILER_SUPPORTS_CXX11)
 6    set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11")
 7 elseif(COMPILER_SUPPORTS_CXX0X)
 8    set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++0x")
 9 else()
10    message(FATAL_ERROR "The compiler ${CMAKE_CXX_COMPILER} has no C++11 support. Please use a different C++ compiler.")
11 endif()

 


 

2017.12.15

今天被问到static修饰的局部变量如果在并行时会怎样,当时有点懵,知道并行的时候是要加互斥锁的,不过如果不加会怎样呢,没有写过并行啊,会乱吧,回来拿多线程试了一下,还是mutex那段代码:

void print_block(int n, char c) {
    mtx.lock();
    static int i = 0;
    for (i = 0; i<n; ++i) { std::cout << c<<i; }
    std::cout << '\n';
    mtx.unlock();
}

如果加了互斥锁,不管是不是静态输出都长这样:

不加互斥锁,静态局部变量 static int i 输出:

非静态局部变量 int i 输出:

个人理解:

用static修饰的局部变量在编译时初始化好,存储在全局区域,不过多少个线程,都去访问这个局部变量;

而没有用static修饰的局部变量在函数调用的时候才分配空间,放在堆栈,这里用多线程,那么每个线程建立的时候给它分配一次内存,并且是从线程自己的堆栈空间里分配出来的。

晚饭后继续试,下面这段代码:

int staticTest(int n)
{
    static int idx = 0;
    
    idx = n-1;
cout << idx; if(idx) staticTest(idx ); return 1; } int _tmain(int argc, _TCHAR* argv[]) { std::thread th1(staticTest, 5); std::thread th2(staticTest, 8); th1.join(); th2.join(); cout << "hello world" << endl; return 0; }

输出长这样:

去掉static以后:

静态加上互斥:

    mtx.lock();
    cout << idx;
    mtx.unlock();

这里 c/c++中的static关键字详解 用法1 解释了上述现象:

用法1:函数内部声明的static变量,可作为对象间的一种通信机制
    如果一局部变量被声明为static,那么将只有唯一的一个静态分配的对象,它被用于在该函数的所有调用中表示这个变量。这个对象将只在执行线程第一次到达它的定义使初始化。

仍旧觉得有点乱,暂且保留敬畏心,static要慎用(依稀记得小时候编单片机很常用,可以用很巧妙的方式做定时器计数,不过单片机不用多线程啊)

参考:static静态变量的理解

posted @ 2017-11-30 17:22  tszs_song  阅读(1241)  评论(0编辑  收藏  举报