C++ C++;线程:从主线程触发一个循环
我有4个传感器,我想在4个不同的线程内异步轮询。我有一个计时器,将调用30Hz的函数,我希望这个函数触发线程内的轮询 我曾尝试使用C++ C++;线程:从主线程触发一个循环,c++,multithreading,c++14,C++,Multithreading,C++14,我有4个传感器,我想在4个不同的线程内异步轮询。我有一个计时器,将调用30Hz的函数,我希望这个函数触发线程内的轮询 我曾尝试使用std::async在每次计时器调用时生成4个线程,但创建线程的开销太大。下面是我对std::async所做的操作: 用于(自动和相机:相机\矢量){ 摄像机不同步,后置( std::async(std::launch::async,[camera]()->bool{ 返回摄像头->轮询(); }) ); } 用于(自动和未来:相机异步){ future.get();
std::async
在每次计时器调用时生成4个线程,但创建线程的开销太大。下面是我对std::async
所做的操作:
用于(自动和相机:相机\矢量){
摄像机不同步,后置(
std::async(std::launch::async,[camera]()->bool{
返回摄像头->轮询();
})
);
}
用于(自动和未来:相机异步){
future.get();
}
现在我需要在程序开始时生成4个线程,并等待时钟通知它们解锁并运行进程函数。大概是这样的:
用于(自动和相机:相机\矢量)
{
摄影机线程放置回(std::thread([&camera](){
while(true)
{
等待触发器();
摄像头->轮询();
块_触发器();
}
}));
}
无效驱动程序::轮询线程(){
用于(自动线程:摄影机线程(&U){
触发器线程(线程);
}
}
你会怎么做?我的研究让我找到了互斥体和条件变量。例如但我发现的例子是开始一堆线程,然后让它们结束。不要一次触发一个线程中的一个循环
另外,这里我需要的似乎不是一个线程池,因为每个线程作为一个定义的作业,只需要一个触发器。我说得对吗
在我看来,使用互斥体是正确的做法。我应该将它们存储在与线程向量大小相同的第二个向量中吗?我知道我可以在线程内锁定互斥体,但是我可以从主线程解锁互斥体吗?你有什么建议来实现这一点吗
我正在使用C++14
感谢您的帮助。以下是我对您需求的理解:
#include <thread>
#include <vector>
#include <chrono>
#include <iostream>
#include <atomic>
using namespace std;
std::atomic_flag lock0 = ATOMIC_FLAG_INIT;
std::atomic_flag lock1 = ATOMIC_FLAG_INIT;
std::atomic_flag lock2 = ATOMIC_FLAG_INIT;
std::atomic_flag lock3 = ATOMIC_FLAG_INIT;
void trigger() {
while (true) {
lock0.clear(); // set to false
lock1.clear(); // set to false
lock2.clear(); // set to false
lock3.clear(); // set to false
std::this_thread::sleep_for(std::chrono::milliseconds(33)); // 33 ms = 1000ms/30
// from now on, all threads lost the chance to be triggered
// they have to wait for the next time
lock0.test_and_set(); // set to true
lock1.test_and_set(); // set to true
lock2.test_and_set(); // set to true
lock3.test_and_set(); // set to true
}
}
void f0()
{
while (true) {
while(!lock0.test_and_set()) {
std::cout << "f0" << std::endl;
}
}
}
void f1()
{
while (true) {
while(!lock1.test_and_set()) {
std::cout << "f1" << std::endl;
}
}
}
void f2()
{
while (true) {
while(!lock2.test_and_set()) {
std::cout << "f2" << std::endl;
}
}
}
void f3()
{
while (true) {
while(!lock3.test_and_set()) {
std::cout << "f3" << std::endl;
}
}
}
int main()
{
std::vector<std::thread> v; // use std::async if you want
std::thread t(trigger);
v.emplace_back(f0);
v.emplace_back(f1);
v.emplace_back(f2);
v.emplace_back(f3);
for (auto &ele : v) {
ele.join();
}
t.join();
return 0;
}
#包括
#包括
#包括
#包括
#包括
使用名称空间std;
std::atomic_flag lock0=atomic_flag_INIT;
std::atomic_flag lock1=atomic_flag_INIT;
std::atomic_flag lock2=atomic_flag_INIT;
std::atomic_flag lock3=atomic_flag_INIT;
无效触发器(){
while(true){
lock0.clear();//设置为false
lock1.clear();//设置为false
lock2.clear();//设置为false
lock3.clear();//设置为false
std::this_thread::sleep_for(std::chrono::毫秒(33));//33毫秒=1000ms/30
//从现在起,所有线程都失去了被触发的机会
//他们不得不等待下一次
lock0.test_和_set();//设置为true
lock1.test_和_set();//设置为true
lock2.test_和_set();//设置为true
lock3.test_和_set();//设置为true
}
}
void f0()
{
while(true){
而(!lock0.test_和_set()){
std::那么当计时器触发时,它会产生另外四个新线程吗?在线程内部执行等待难道不是更有意义吗,否则主线程仍然会为发送线程信号而烦恼吗?@Yves理想情况下不会,我希望线程等待触发。看起来你需要的确实是一个线程池。它会ld允许您保持4个线程的活动状态,并在必要时唤醒它们(当您给线程池一个要执行的任务时)。但是对于互斥体和条件变量,这基本上是相同的:)@Fareanor最简单的方法是什么?有什么建议吗?那么我应该有一个互斥体吗?请注意,在诸如test\u和\u set
之类的操作上旋转效率极低,因为它涉及缓存争用。最好在锁解锁之前,在普通加载/读取上旋转。此外,在这个设置中,所有的原子标记都可能在同一个高速缓存行中结束,这会使事情变得更糟。我会考虑将它们对齐到缓存行,例如用<代码>对齐(64)。
@DanielLangr非常有用的信息。@DanielLangr但是std::atomic_flag
不提供加载或存储操作…有什么建议吗?当然,你看过我发布的链接了吗?他们在那里使用std::atomic
。