c++线程笔记

c++线程笔记

使用pthread.h,由于是c非标准库,因此需要加入-lpthread参数编译:

Linux下:

CMAKE:

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

VSCode:

在tasks.json中添加参数            “-lpthread”,

Windows:

Visual Studio :

>>工具 >>选项 >>跨平台 >>连接管理器 添加ssh连接

>>项目 >>属性 >>链接器 >>输入 在库依赖项中添加pthread

>>项目 >>属性 >>链接器 >>常规 配置类型选择.out

其他选项默认设置或者按照自己需求配置。

函数中添加一下头文件

#include <pthread.h>

创建线程:

pthread_create(&post_moto_threadNULLMotoAction_Oneargss)

返回值

若成功则返回0,否则返回出错编号

post_moto_thread        为pthread_t类型,保存线程ID,

NULL                设定线程属性

MotoAction            线程运行函数的起始地址 void*指针

Argss                运行函数的参数    void*指针

函数定义如下:

void *MotoAction_One(void *arg)

可以通过强制转换

*(uint16_t*)arg)

还原数据

数据类型:(重要!!!!!!!)

Either pthread_join(3) or pthread_detach() should be called for each thread

that an application creates, so that system resources for the thread can be

released. (But note that the resources of all threads are freed when the

process terminates.)

线程需要指定线程属性,这样在线程结束的时候所有资源都会被系统回收,否则将会占用。

pthread_join(线程ID)将阻塞当前线程直到线程ID对应的线程结束,并回收资源,

pthread_detach(线程ID)非阻塞型,设置好属性后继续执行,线程结束后自动回收。

在创建的时候将属性设置为NULL方便在合适的地方再次定义类型,例如创建10个线程下载不同的配置文件,所有线程创建完毕后执行pthread_join等待所有线程结束再进行下一步。

若不配置属性

static
void* pthread_test(void* arg) {

cout <<
“thread start”
<< endl;

cout <<
“thread stop”
<< endl;

pthread_exit(0);

}

cout <<
“main is started!”
<< endl;

for (int i = 0; i < 1000; i++)

{


for (int j = 0; j < 10; j++)

{

s = pthread_create(&thrWrite_1, NULL, pthread_test, NULL); // 开启线程

    if (s != 0)

            std::cout <<
“pthread_create error: error_code=”
<< s << std::endl; //

        thread_q.push(thrWrite_1);

    }

    scanf(“%d”, &s);

}

Vs调试,linux用free查看内存:

启动程序,开启线程前:

开启1000个线程并且线程结束后

可用内存减少了

继续开启全部线程:

看free那列,可用内存显著减少了。

运行pthread_join

while (thread_q.size())

{

pthread_join(thread_q.front(), NULL);

thread_q.pop();

}

内存回来了

对于以下代码,分析问题(已省略属性配置):

static void* randsleep(void* arg);

for(int i=0; i<100; i++){

uint16_t argss[2] = {rand()%10, rand()%10};

if (pthread_create(&post_moto_thread[i], NULL, randsleep, argss))

{

std::cout << “pthread_create error: moto_code=” << i << std::endl;

}

}

static void* randsleep(void* arg) {

int moto_n, count;

moto_n = *(uint16_t*)arg;

count = *((uint16_t*)arg+1);

cout<< moto_n<< endl;

cout<< count << endl;

}

看代码逻辑并没有什么问题,而实际上并非如此,argss属于局部变量,在for循环中对应的内存地址不会变,而我们传入线程的参数恰恰是地址指针,这将导致线程创建成功后,主线程继续执行,改变了argss的数值后,子线程才运行到赋值部分,这样程序并不会报错,当得到的运行结果不是我们想要的,这里有两种解决办法:

第一种:

在创建线程后添加sleep函数等待一点时间,优点是简单,确定便是时间不好把控,设置大了影响性能。

第二种:

利用new关键字动态分配内存,在线程中delete释放,优点是不存在不必要的性能浪费,代码效率较高且可分析,缺点是稍占内存空间,分配和释放内存不在同一代码段,不易于大后期维护,必须添加备注!

static void* randsleep(void* arg);

for(int i=0; i<100; i++){

uint16_t* argss = new uint16_t[2];

argss[0] = rand()%10;

argss[1] = rand()%10;

if (pthread_create(&post_moto_thread[i], NULL, randsleep, argss))

{

std::cout << “pthread_create error: moto_code=” << i << std::endl;

}

}

static void* randsleep(void* arg) {

int moto_n, count;

moto_n = *(uint16_t*)arg;

count = *((uint16_t*)arg+1);

delete [](uint16_t*)arg;

cout<< moto_n<< endl;

cout<< count << endl;

}

感叹一句queue真好用!!!!

参考资料:

https://www.cnblogs.com/wanqieddy/p/4381212.html

https://www.cnblogs.com/zhangjiansheng/p/9332799.html

moller_1
moller_1
文章: 16

留下评论

您的电子邮箱地址不会被公开。 必填项已用*标注