学习视频与书籍
学习视频
c++11并发与多线程视频课程
学习书籍
我本来打算去图书馆借《C++新经典》的,偶然发现这本书,如获至宝
- 书挺新的,我看译者序是21年10月
- 这本书挺贵的,后面写着139.80,大家还是去图书馆借吧
- 作为基础与入门我觉得看前5章应该就够了
基本概念
C++11并发与多线程笔记(1) 并发基本概念及实现,进程、线程基本概念
进程
运行起来的可执行程序
线程
- 每个进程都有一个主线程
- 主线程随着进程的启动而启动
- 同一个进程可以通过代码创建其它线程
- 线程用来执行代码,可以理解为代码的执行通路
- 线程的存在使得可以在同一时刻干多个不同的事
💡 线程并不是越多越好,每个线程,都需要一个独立的堆栈空间(大约1M),线程之间的切换要保存很多中间状态,切换也会耗费本该属于程序运行的时间
并发
多进程并发
- 比如账号服务器一个进程,游戏服务器一个进程
- 服务器进程之间存在通信(同一个电脑上:管道,文件,消息队列,共享内存;不同电脑上:socket通信技术)
多线程并发
- 线程像是轻量级的进程。每个进程有自己独立的运行路径,但一个进程中的所有线程共享地址空间(共享内存),全局变量、全局内存、全局引用都可以在线程之间传递,所以多线程开销远远小于多进程
- 多进程并发和多线程并发可以混合使用,但建议优先考虑多线程技术
线程管控
线程的基本管控
基本操作
- 包含头文件
- 构造std::thread实例
- 向该实例提供可调用对象
💡 新线程必须包含入口函数
可调用函数对象包括:
- 函数
- 函数指针
- lambda表达式
- bind创建的对象
- 函数对象(仿函数)
实例
#include <thread>
#include <iostream>
using namespace std;
class MyPrint
{
public:
MyPrint()
{
cout << "默认构造函数...." << endl;
}
void operator()()
{
cout << "线程开始执行!" << endl;
cout << "线程结束执行!" << endl;
}
~MyPrint()
{
cout << "析构函数...." << endl;
}
};
int main()
{
// MyPrint myprint;
thread my_thread{MyPrint()};
if(my_thread.joinable())
{
cout << "Thread joinable...." << endl;
// my_thread.join();
my_thread.detach();
}
else
{
cout << "Unable to join...." << endl;
}
cout << "Life is for coding!" << endl;
return 0;
}
注意点:
- 将函数对象传递给thread构造函数时,实际调用了类的默认拷贝构造函数,内存中多了一份数据
- 类必须重载函数操作符( ),才可作为参数传递给thread对象
- 传递匿名对象是要用大括号
- join( )阻塞主线程,主线程等待所有次线程完成后运行后续语句
- detach( )主线程、次线程各走各的,主线程结束后次线程在后台继续运行但无显示和输出
- 使用join( )和detach( )前先用joinable( )进行判断
变量生存期问题
次线程可能会访问外部数据,如局部变量等
若是函数内的局部变量,函数运行结束局部变量即销毁,此时访问该变量会产生未定义行为
可以理解为野指针或浅拷贝的问题
解决方法:
- 将数据复制到新线程内部,而不是共享数据
- 在函数中汇合新线程,确保函数退出前新线程执行完毕
对‘pthread_create’未定义的引用
我是在Linux下编程,没用gcc进行编译,写的CMakeLists.txt,在build目录下make时报错
对‘pthread_create’未定义的引用
gcc编译报错的解决
对pthread_create未定义的引用
因为还未详细用到pthread,先列出以供后续了解
pthread与std::thread的区别与应用
C++多线程pthread和thread
应该是我CMakeLists.txt写的不对,参考
c++多线程 CMakeLists设置
我的CMakeLists.txt更改如下:
cmake_minimum_required(VERSION 2.8)
project(Cplus_learning)
SET(CMAKE_CXX_COMPILER "g++")
#set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11 -pthread")
set(EXECUTABLE_OUTPUT_PATH ${PROJECT_SOURCE_DIR}/bin)
# add_subdirectory(src bin)
add_executable(thread_01 src/thread_01.cpp)
可以正常编译并运行