C/C++中的多线程说明

文章目录

  • 简介
  • POSIX线程
    • Windows环境下使用POSIX线程
      • 下载windows环境下使用的pthread库
      • visual studio下的传统解决方案sln项目的演示集成
      • visual studio下的Cmake项目的演示集成
      • 使用Cmake项目时出现的问题及解决方法
    • Linux环境下使用POSIX线程
      • 1.环境准备
      • 2. 创建一个普通工程目录来演示
      • 3.创建一个Cmake项目来演示
  • C++11的多线程
  • 两种多线程的不同

简介

在C/C++中,有两种线程库,一种是POSIX标准的POSIX线程,另一个是C++11开始支持的标准库提供的多线程。POSIX标准提供的POSIX线程,在C++11开始之前就有,而且现在仍然再用。

POSIX线程

在Unix/Linux系统中,C/C++提供了pthread(POSIX线程)API。它允许我们为并发流程创建多个线程,这可以提高程序在多核处理器或上的执行速度。
想要使用pthreads库的所有功能,我们必须在.c或.c++文件中包含pthread.h头文件,在编译文件时在命令行中使用 -pthread 或 -lpthread(由于pthreads库并不是标准库提供的,而是Linux或Unix系统自带的,一般这个库是在系统环境变量下的路径中的,所以这里只用-pthread 指定,会自动从系统环境变量的路径下查找libthreads),
pthread选项对 预处理器和链接器起作用 而老式的-lpthread只对链接器起作用。
引入POSIX线程多线程头文件 需要 使用 #include <pthread.h>

Windows环境下使用POSIX线程

下载windows环境下使用的pthread库

链接:https://pan.baidu.com/s/1pdEH_5KcDu4Qt5S8G_IC_g
提取码:jd6a
下载后解压:
C/C++中的多线程说明_第1张图片
C/C++中的多线程说明_第2张图片
我们可以采用动态链接的隐式链接的方式集成到项目中使用。
仅使用多线程的话,这里用到的头文件为:include下的pthread.h
dll和lib目录下都又分x86和x64,具体使用多少位数,根据自己开发的项目软件位数有关。
这里使用x86目录下的来演示:
dll\x86\pthreadVC2.dll
\lib\x86\pthreadVC2.lib

visual studio下的传统解决方案sln项目的演示集成

新建一个空项目
C/C++中的多线程说明_第3张图片
将lib文件夹和include的文件拷贝到项目目录下
C/C++中的多线程说明_第4张图片

main.cpp中的内容如下:

#include 
#include "./include/pthread.h"
#pragma comment(lib,"./lib/x86/pthreadVC2.lib")

void* __cdecl test(void *arg) {
	std::cout << "执行线程!" << std::endl;
	return 0;
}

void test_pthread() {
	pthread_t tid;//声明pthread_t的对象,相当于线程的唯一标识,将来用它来操作线程。
  /*第一个参数是线程的唯一标识的地址,pthread_create后,它会指向新创建的线程。
	第二个参数是传给线程函数的额外复合参数,
	第三个参数是函数指针(即函数名),即线程创建后要执行的函数。
	第四个参数函数的形参
  */
	pthread_create(&tid, NULL, test, 0);//创建线程
}
int main(int argc, char* argv[])
{
	test_pthread();
	std::cout << "Hello World" << std::endl;
	system("pause");
	return 1;
}

平台编译环境:
在这里插入图片描述

然后点击 生成下的 生成解决方案, 会在解决方案目录下的Debug目录看到demoPthreadUse.exe文件。
然后将dll\x86\pthreadVC2.dll 放到C:\Windows\SysWOW64目录下,或者 exe文件的当前目录下。然后执行exe文件。
查看运行效果:
C/C++中的多线程说明_第5张图片

visual studio下的Cmake项目的演示集成

新建一个Cmake项目
C/C++中的多线程说明_第6张图片
C/C++中的多线程说明_第7张图片

项目目录结构:
C/C++中的多线程说明_第8张图片

工程项目下的那个CMakeLists.txt内容如下:

# CMakeList.txt: CMakeProject1 的 CMake 项目,在此处包括源代码并定义
# 项目特定的逻辑。
#
cmake_minimum_required (VERSION 3.8)

# 添加头文件目录INCLUDE_DIRECTORIES
# 它相当于g++选项中的-I参数的作用,也相当于环境变量中增加路径到CPLUS_INCLUDE_PATH变量的作用。
# 语法:
# include_directories([AFTER|BEFORE] [SYSTEM] dir1 [dir2 ...])
include_directories ("./include")	#相当于传统工程下的包含目录

# 添加需要链接的静态库文件目录LINK_DIRECTORIES
link_directories("./lib/x86")		#相当于传统工程下的库目录

# 添加需要lib库文件目录LINK_LIBRARIES
# 语法:
#link_libraries(library1  library2 ...)]
# 根据link_directories里的目录和这里的文件名pthreadVC2,然后查找pthreadVC2.lib文件
link_libraries(pthreadVC2) #这里的文件名默认按.lib。相当于传统工程下的附件依赖项

# 将源代码添加到此项目的可执行文件。 注意link_libraries 项要配置 add_executable 项之前
#这里的第一个是生成的可执行文件的名称,第二个参数开始就是自己写的源文件,头文件可以不用写进来
add_executable (CMakeProject1 "CMakeProject1.cpp")

#这个作用不太清楚,以后用到再说,但是target_link_libraries项要配置在 add_executable 项之后
#target_link_libraries(CMakeProject1 pthreadVC2.dll)


# TODO: 如有需要,请添加测试并安装目标。

cpp源文件里的内容:

// CMakeProject1.cpp: 定义应用程序的入口点。

#include "CMakeProject1.h"
#include "pthread.h"
using namespace std;

void* test(void *arg)
{
	cout << "执行新创建的线程" << endl;
	return (void*)0;
}

int main()
{
	pthread_t threadId;
	pthread_create(&threadId, NULL, test, 0);
	pthread_join(threadId, 0);
	cout << "程序执行完毕!" << endl;
	system("pause");
	return 0;
}

个人认为这一步,应该是cmake命令根据CMakeList.txt文件中的描述来生成makefile文件。如果配置什么的都没有问题。会在out\build目录下生成对应的平台的文件,这个时候可执行文件还没有生成。
C/C++中的多线程说明_第9张图片
C/C++中的多线程说明_第10张图片
如果生成成功的话:会在out\build\x86-Release\CMakeProject1目录下生成可执行文件:
C/C++中的多线程说明_第11张图片
把dll库文件放到C:\Windows\SysWOW64目录下或和可执行文件的同级目录下,运行可执行文件:
C/C++中的多线程说明_第12张图片
可以发现上面的配置的cmake工程的DLL库的使用 也是采用的动态链接的隐式链接方式。

使用Cmake项目时出现的问题及解决方法

在这里插入图片描述
这样在out/build目录下就会自动生成相应平台的目录,这里选择的平台是x86-Release。再点击生成 就不会报错了。

Linux环境下使用POSIX线程

1.环境准备

1.Linux环境下使用POSIX线程,不用像Windows上使用需要单独去下载,因为Liunx系统库自带pthread线程库。我们可以通过以下命令查看

root@localhost ~]# g++ -v
-bash: g++: 未找到命令
[root@localhost ~]# gcc -v
-bash: gcc: 未找到命令
[root@localhost ~]# find / -name libpthread.so
/usr/lib64/libpthread.so
[root@localhost ~]# find / -name pthread.h
/usr/include/pthread.h
[root@localhost ~]# find / -name libpthread.a
[root@localhost ~]# find / -name pthread.a
[root@localhost ~]#

发现即使没有安装GNU套件也存在动态库libpthread.so和头文件pthread.h。Linux上没有提供pthread线程的静态库。
下面要在Linux上演示,要把gcc/g++安装上。
安装命令:默认安装版本为4.8.5
[root@localhost ~]# yum -y install gcc gcc-c++ kernel-devel
执行完毕后:
C/C++中的多线程说明_第13张图片

2. 创建一个普通工程目录来演示

[root@localhost ~]# mkdir commonProject
[root@localhost ~]# cd commonProject/
[root@localhost commonProject]# mkdir proj01
[root@localhost proj01]# touch main.cpp
然后用EditPlus连接上,在其中编辑main.cpp文件
C/C++中的多线程说明_第14张图片
编译源文件

没有加链接动态库情况下
[root@localhost proj01]# g++ main.cpp
/tmp/ccn2QIJ0.o:在函数‘main’中:
main.cpp:(.text+0x55):对‘pthread_create’未定义的引用
main.cpp:(.text+0x66):对‘pthread_join’未定义的引用
collect2: 错误:ld 返回 1

加了链接动态库的情况下
[root@localhost proj01]# g++ main.cpp -lpthread
[root@localhost proj01]# ll
总用量 16
-rwxr-xr-x. 1 root root 9120 4月 20 18:09 a.out #生成的可执行文件
-rw-r–r–. 1 root root 339 4月 20 18:08 main.cpp
#注意这里 -l是linker的缩写,pthread是libpthread.so文件的缩写。不能写成libpthread.so,也不能写成pthread.so或者libpthread。只能写成pthread,这是Linux环境约定的规则。-lpthread 会自动链接查找libpthread.so

执行a.out文件

[root@localhost proj01]# ./a.out
执行新创建的线程
程序执行完毕!

这里要说明一下:pthread.h 编译器会自动从/usr/include/目录下搜索。libpthread.so文件编译器 会自动从/usr/lib64/目录下搜索。

3.创建一个Cmake项目来演示

安装cmake环境
安装gcc程序开发基础包,前面安装的时候把make拉下了。这里在执行下次命令会把make命令也安装上。
yum install -y gcc gcc-c++ make automake
获取Cmake源码包
wget https://cmake.org/files/v3.6/cmake-3.6.2.tar.gz
解压CMake源码包
tar -zxvf cmake-3.6.2.tar.gz
进入目录
cd cmake-3.6.2
编译安装
$ ./bootstrap && make -j4 && sudo make install
静等一会时间…
安装完毕之后,用cmake -version命令查看下,如果执行成功,表明安装成功了。
C/C++中的多线程说明_第15张图片
创建一个空项目CmakeProject,项目结构如下:
C/C++中的多线程说明_第16张图片
CMakeList.txt文件内容:

# CMakeList.txt: CmakeProject 的 CMake 项目,在此处包括源代码并定义
# 项目特定的逻辑。
#
cmake_minimum_required (VERSION 3.6)
#指定查找头文件的路径
include_directories("/usr/include/")

#这里的第一个是生成的可执行文件的名称,第二个参数开始就是自己写的源文件,头文件可以不用写进来
#link_libraries用在add_executable之前,target_link_libraries用在add_executable之后
link_libraries("/usr/lib64/libpthread.so")

add_executable(CmakeProject "./src/main.cpp")

#target_link_libraries(CmakeProject libpthread.so) #显示指定链接动态库
#下面这几种写法也是可以的
#target_link_libraries(CmakeProject pthread)    #连接libpthread.so库,默认优先链接动态库
#target_link_libraries(CmakeProject libpthread.a)  #显示指定链接静态库,虽然此库没有,这里只是说明可以链接静态库
#target_link_libraries(CmakeProject -lpthread)

# TODO: 如有需要,请添加测试并安装目标。

[root@localhost build]# pwd
/root/CmakeProject/build

[root@localhost build]# cmake …
– Configuring done
– Generating done
– Build files have been written to: /root/CmakeProject/build
[root@localhost build]# ll #查看生成的内容
总用量 28
-rw-r–r–. 1 root root 11529 4月 20 20:05 CMakeCache.txt
drwxr-xr-x. 5 root root 4096 4月 20 20:09 CMakeFiles
-rw-r–r–. 1 root root 1353 4月 20 20:08 cmake_install.cmake
-rw-r–r–. 1 root root 4899 4月 20 20:09 Makefile

[root@localhost build]# cmake --build .
Scanning dependencies of target CmakeProject
[ 50%] Building CXX object CMakeFiles/CmakeProject.dir/src/main.cpp.o
[100%] Linking CXX executable CmakeProject
[100%] Built target CmakeProject
[root@localhost build]# ll
总用量 40
-rw-r–r–. 1 root root 11529 4月 20 20:05 CMakeCache.txt
drwxr-xr-x. 5 root root 4096 4月 20 20:11 CMakeFiles
-rw-r–r–. 1 root root 1353 4月 20 20:08 cmake_install.cmake
-rwxr-xr-x. 1 root root 9120 4月 20 20:11 CmakeProject #这个就是生成的可执行文件
-rw-r–r–. 1 root root 4899 4月 20 20:09 Makefile

C/C++中的多线程说明_第17张图片
查看可执行文件运行效果:

[root@localhost build]# ./CmakeProject
执行新创建的线程
CMake构建的程序执行完毕!

C++11的多线程

从C++11开始,标准库里已经包含了对线程的支持,std::thread是C++11标准库中的多线程的支持库,pthread.h是 标准库没有添加多线程之前的在Linux上用的多线程库,而之前在windows上的多线程支持要包含wndows.h。
引入C++11的多线程头文件 需要 使用 #include <thread>

两种多线程的不同

由于C++11 提供的标准库中的多线程,存在一定的缺陷,目前多线程用的多的,还是POSIX线程。
C++ 11发布之前,C++并没有对多线程编程的专门支持,C++ 11通过标准库引入了对多线程的支持,大大方便了程序员的工作。需要说明的是,C++ 11标准库内部包裹了pthread库,因此,编译程序的时候需要加上-lpthread连接选项.

你可能感兴趣的:(C,and,C++的笔记,c语言,c++,linux)