线程处理 returns 意外结果 - C++
Threading returns unexpected result - c++
我正在学习有关线程的作业,并且我尝试在我编写的一个简单程序上实现线程。没有线程程序可以完美运行,但是当我线程化两个随机数生成器函数时,它 returns 不正确的结果。两个数字生成器的结果似乎总是“42”,不确定为什么会这样。
同样对于上下文,我只是从线程开始,所以我知道这个程序不需要多线程。我这样做只是为了学习目的。
感谢您的帮助!
// struct for vector to use
struct readings {
std::string name;
int data;
};
// random generator for heat value - stores in vector of struct
void gen_heat(std::vector<readings>& storage) {
readings h = {"Heat", rand() % 100 + 1};
storage.insert(storage.begin(), h);
}
// random generator for light value - stores in vector of struct
void gen_light(std::vector<readings>& storage) {
readings l = {"Light", rand() % 100 + 1};
storage.insert(storage.begin(), l);
}
int main() {
// vector of readings struct
std::vector<readings> storage;
srand(time(NULL));
// initialising threads of random generators
std::thread H(gen_heat, std::ref(storage));
std::thread L(gen_light, std::ref(storage));
// waiting for both to finish
H.join();
L.join();
// print values in vec of struct
for (const auto& e : storage) {
std::cout << "Type: " << e.name << std::endl
<< "Numbers: " << e.data << std::endl;
}
// send to another function
smartsensor(storage);
return 0;
}
由于您有多个线程访问一个共同资源,在本例中为读数向量,并且其中一些线程正在修改它,因此您需要独占访问该资源。同步访问的方式有很多种;其中之一是 binary semaphore(C++20 起),它足够简单且不会深入到互斥体的使用。你基本上:
- 通过获取信号量拥有对资源的访问权,
- 使用资源,然后,
- 释放信号量以便其他人可以访问该资源。
如果线程 A
试图获取信号量,而其他线程 B
正在使用资源,线程 A
将阻塞,直到资源被释放。
请注意,信号量已初始化为 1
,表示资源空闲。一旦一个线程获取了信号量,计数将下降到 0
,并且在计数回到 1
之前没有其他线程能够获取它(在 [=18= 之后会发生什么) ]).
#include <cstdlib> // rand
#include <iostream> // cout
#include <semaphore>
#include <string>
#include <thread>
#include <vector>
std::binary_semaphore readings_sem{1};
// struct for vector to use
struct readings {
std::string name;
int data;
};
// random generator for heat value - stores in vector of struct
void gen_heat(std::vector<readings>& storage) {
for (auto i{0}; i < 5; ++i) {
readings_sem.acquire();
readings h = {"Heat", rand() % 100 + 1};
storage.insert(storage.begin(), h);
readings_sem.release();
}
}
// random generator for light value - stores in vector of struct
void gen_light(std::vector<readings>& storage) {
for (auto i{0}; i < 5; ++i) {
readings_sem.acquire();
readings l = {"Light", rand() % 100 + 1};
storage.insert(storage.begin(), l);
readings_sem.release();
}
}
int main() {
// vector of readings struct
std::vector<readings> storage;
srand(time(NULL));
// initialising threads of random generators
std::thread H(gen_heat, std::ref(storage));
std::thread L(gen_light, std::ref(storage));
// waiting for both to finish
H.join();
L.join();
// print values in vec of struct
for (const auto& e : storage) {
std::cout << "Type: " << e.name << std::endl
<< "Numbers: " << e.data << std::endl;
}
}
// Outputs (something like):
//
// Type: Heat
// Numbers: 5
// Type: Light
// Numbers: 83
// Type: Light
// Numbers: 40
// ...
[Ben Voigt 评论的更新]
资源的获取和释放可以使用RAII(Resource Acquisition Is Initialization)封装,语言已经提供了这种机制。例如:
- 两个线程仍然尝试获取互斥锁以访问读数资源向量。
- 但他们通过创建
lock guard
. 获得它
- 一旦锁守卫超出范围并被销毁,互斥体就会被释放。
#include <mutex> // lock_guard
std::mutex mtx{};
// random generator for heat value - stores in vector of struct
void gen_heat(std::vector<readings>& storage) {
for (auto i{0}; i < 5; ++i) {
std::lock_guard<std::mutex> lg{ mtx };
readings h = {"Heat", rand() % 100 + 1};
storage.insert(storage.begin(), h);
}
}
我正在学习有关线程的作业,并且我尝试在我编写的一个简单程序上实现线程。没有线程程序可以完美运行,但是当我线程化两个随机数生成器函数时,它 returns 不正确的结果。两个数字生成器的结果似乎总是“42”,不确定为什么会这样。
同样对于上下文,我只是从线程开始,所以我知道这个程序不需要多线程。我这样做只是为了学习目的。
感谢您的帮助!
// struct for vector to use
struct readings {
std::string name;
int data;
};
// random generator for heat value - stores in vector of struct
void gen_heat(std::vector<readings>& storage) {
readings h = {"Heat", rand() % 100 + 1};
storage.insert(storage.begin(), h);
}
// random generator for light value - stores in vector of struct
void gen_light(std::vector<readings>& storage) {
readings l = {"Light", rand() % 100 + 1};
storage.insert(storage.begin(), l);
}
int main() {
// vector of readings struct
std::vector<readings> storage;
srand(time(NULL));
// initialising threads of random generators
std::thread H(gen_heat, std::ref(storage));
std::thread L(gen_light, std::ref(storage));
// waiting for both to finish
H.join();
L.join();
// print values in vec of struct
for (const auto& e : storage) {
std::cout << "Type: " << e.name << std::endl
<< "Numbers: " << e.data << std::endl;
}
// send to another function
smartsensor(storage);
return 0;
}
由于您有多个线程访问一个共同资源,在本例中为读数向量,并且其中一些线程正在修改它,因此您需要独占访问该资源。同步访问的方式有很多种;其中之一是 binary semaphore(C++20 起),它足够简单且不会深入到互斥体的使用。你基本上:
- 通过获取信号量拥有对资源的访问权,
- 使用资源,然后,
- 释放信号量以便其他人可以访问该资源。
如果线程 A
试图获取信号量,而其他线程 B
正在使用资源,线程 A
将阻塞,直到资源被释放。
请注意,信号量已初始化为 1
,表示资源空闲。一旦一个线程获取了信号量,计数将下降到 0
,并且在计数回到 1
之前没有其他线程能够获取它(在 [=18= 之后会发生什么) ]).
#include <cstdlib> // rand
#include <iostream> // cout
#include <semaphore>
#include <string>
#include <thread>
#include <vector>
std::binary_semaphore readings_sem{1};
// struct for vector to use
struct readings {
std::string name;
int data;
};
// random generator for heat value - stores in vector of struct
void gen_heat(std::vector<readings>& storage) {
for (auto i{0}; i < 5; ++i) {
readings_sem.acquire();
readings h = {"Heat", rand() % 100 + 1};
storage.insert(storage.begin(), h);
readings_sem.release();
}
}
// random generator for light value - stores in vector of struct
void gen_light(std::vector<readings>& storage) {
for (auto i{0}; i < 5; ++i) {
readings_sem.acquire();
readings l = {"Light", rand() % 100 + 1};
storage.insert(storage.begin(), l);
readings_sem.release();
}
}
int main() {
// vector of readings struct
std::vector<readings> storage;
srand(time(NULL));
// initialising threads of random generators
std::thread H(gen_heat, std::ref(storage));
std::thread L(gen_light, std::ref(storage));
// waiting for both to finish
H.join();
L.join();
// print values in vec of struct
for (const auto& e : storage) {
std::cout << "Type: " << e.name << std::endl
<< "Numbers: " << e.data << std::endl;
}
}
// Outputs (something like):
//
// Type: Heat
// Numbers: 5
// Type: Light
// Numbers: 83
// Type: Light
// Numbers: 40
// ...
[Ben Voigt 评论的更新]
资源的获取和释放可以使用RAII(Resource Acquisition Is Initialization)封装,语言已经提供了这种机制。例如:
- 两个线程仍然尝试获取互斥锁以访问读数资源向量。
- 但他们通过创建
lock guard
. 获得它
- 一旦锁守卫超出范围并被销毁,互斥体就会被释放。
#include <mutex> // lock_guard
std::mutex mtx{};
// random generator for heat value - stores in vector of struct
void gen_heat(std::vector<readings>& storage) {
for (auto i{0}; i < 5; ++i) {
std::lock_guard<std::mutex> lg{ mtx };
readings h = {"Heat", rand() % 100 + 1};
storage.insert(storage.begin(), h);
}
}