多线程时的参数请用new生成

时间:2023-02-13 21:08:27

多线程是编程中常用技术,本人由于长久不用,竟然不小心犯了多线程共同使用主线程地址数据的错误。下面概要的介绍下thread的主要函数,并举例梳理下使用thread参数传输错误的原因。

一、thread基本介绍

C++11 新标准中引入了四个头文件来支持多线程编程,他们分别是<atomic> ,<thread>,<mutex>,<condition_variable>和<future>

<thread>:该头文件主要声明了 std::thread 类。


主要的函数如下:

Member functions

其中构造函数:

default (1)
thread() noexcept;
initialization (2)
template <class Fn, class... Args>
explicit thread (Fn&& fn, Args&&... args);
copy [deleted] (3)
thread (const thread&) = delete;
move (4)
thread (thread&& x) noexcept;

二、代码

#include<vector>
#include<thread>
#include<iostream>
#include<windows.h>
using namespace std;


void func1(void* para) {
int data = *(int*)para;
cout << para << ":";
cout<< data << endl;
Sleep(20);
delete (int*)para;
}


void func2(void* para) {
int data = *(int*)para;
cout << para << ":";
cout << data << endl;
Sleep(20);
}


int test1() {
vector<std::thread> vth;
for (int i = 0; i < 30; i++) {
int* j = new int(i);
vth.push_back(thread(func1, j));
}
for (auto& th : vth) {
th.join();
}
return 0;
}


int test2() {
vector<std::thread> vth;
for (int i = 0; i < 30; i++) {
int j = i;
vth.push_back(thread(func2, &j));
}
for (auto& th : vth) {
th.join();
}
return 0;
}


void main() {
test1();
cout << "====================" << endl;
test2();
}


其执行结果如下:

test1:

005DBEF0005DC170005E9DF0:005D77E8005E9D30:20005D8AB8:8
005DB8F8:10
:1
005E9FA0:15
005E9C70:17
:005D7818:5
005E9F10:23
005DFB10:7
005EA000:26
005E65A8:9
005DB928:11
005E9E20:14
13
005E9E50:19
005E9D90:22
005DFAE0:6


005E9EB0:27
005E9F40:12
005D7958:3
4
005E9D60:21
005E9FD0:25
005DBB28:2
005E9DC0:24
005E9F70:16
:0
005E9EE0:29
005E9E80:28
005E9CA0:18


test2:

004EF918004EF918004EF918004EF918:9
004EF918:7004EF918:004EF918004EF918:10
004EF918:4
004EF918:16
004EF918:8
:19
004EF918:21
004EF918:26
004EF918:12
004EF918:29
004EF918:16
004EF918:9

004EF918:22
004EF918:27
004EF918:28
004EF918:17
3
004EF918:24
004EF918:28
004EF918:
004EF918:19
004EF918:11
:2
004EF918:25
004EF918:14:21
6


004EF918:13
004EF918:3
:1

test1属于正常使用,thread创建新线程使用了new出的新地址数据。

test2属于错误试用,thread创建的线程共用了主线程中的数据地址,这样主线程或者任意一个线程对参数j的改变,都会导致多线程其他线程中参数j的变化。

这里thread只有一个简单参数,对于多个子参数组成的结构体参数,需要new生成,然后在新线程中释放即可。