提问人:caccolona 提问时间:11/13/2023 最后编辑:caccolona 更新时间:11/13/2023 访问量:61
使用条件变量和原子布尔值停止 C++ 线程时遇到困难 [已关闭]
Difficulty halting C++ threads using conditional variables and atomic bools [closed]
问:
我在应用程序中停止 C++ 线程时遇到问题。线程函数的核心部分涉及互斥锁和条件变量的使用:
class Acqer {
std::atomic_bool running_;
std::atomic_bool acquiring_;
std::mutex dataMutex;
std::condition_variable acqCV;
std::condition_variable dataCV;
std::jthread acqThread;
std::jthread procThread;
public:
void AcquireData();
void ProcessData();
void StartThreads();
void StopThreads();
};
void Acqer::AcquireData() {
while (running_)
{
// ...
// Lock the mutex
unique_lock<mutex> lock(dataMutex);
// Use a condition variable to start the acquisition
acqCV.wait(lock, [this]() -> bool
{ return acquiring_; });
// ...
// Unlock the mutex
lock.unlock();
// Notify ProcessData thread
dataCV.notify_one();
// ...
}
}
void Acqer::ProcessData() {
while (running_)
{
unique_lock<mutex> lock(dataMutex);
dataCV.wait(lock);
// ...
// Unlock the mutex
lock.unlock();
}
}
void Acqer::StartThreads()
{
running_ = true;
cout << "Starting acquisition and processing threads..." << endl;
acqThread_ = jthread(&Acqer::AcquireData, this);
procThread_ = jthread(&Acqer::ProcessData, this);
cout << "Threads started." << endl;
}
void Acqer::StopThreads()
{
running_ = false;
acqCV.notify_all();
dataCV.notify_all();
}
尽管使用原子布尔值 running_ 和 acquiring_ 以及互斥锁和条件变量,但即使在调用 StopThreads 函数后,线程 AcquireData 仍然存在。 我尝试调试代码,并且我注意到只有在采集尚未开始时才能停止两个线程(acqCV 仍在等待)。
当我将 running_ 设置为 false 时,AcquireData 线程似乎也没有到达 acqCV.wait(...) 行,但仍然不可联接。
是否存在可能阻止这些线程停止的潜在问题或注意事项,即使在信号终止后也是如此?
答:
3赞
Mike Vine
11/13/2023
#1
您正在使用 的谓词形式。这意味着即使应该唤醒线程,如果谓词返回 false,它也会立即再次等待。wait
当你停止线程时,你会唤醒线程,但它会立即再次出现(大概?)false。您还需要签入谓词。请改为执行此操作:AcquireData
wait
acquiring_
_running
acqCV.wait(lock, [this]() -> bool
{ return acquiring_ || !running_; });
if (!_running) break;
评论
0赞
caccolona
11/13/2023
第一部分实际上是我希望线程具有的行为:当 running_ 和 acquiring_ 为 true 时运行 while 循环,同时能够通过将 acquiring_ 设置为 false 来“暂停”它们。AcquireData 似乎在到达 acqCV.wait 行之前就挂起了(虽然不可加入)。
0赞
Mike Vine
11/13/2023
没关系。这仍然会这样做。通过我的更改,当运行设置为 false 时,它还会停止等待并终止循环。这大概是你想要的。否则你的问题就没有意义了?
0赞
caccolona
11/13/2023
我已经添加了这些行,但它仍然不起作用。当我将 AcquireData 设置为 false 时,running_似乎没有到达 acqCV.wait(...) 行,但似乎仍然不可联接。
0赞
Mike Vine
11/13/2023
在这种情况下,需要进行调试。进入你认为你将能够加入的情况,并使用调试器检查这些线程的调用堆栈,以查看它们现在被阻止的确切位置。
0赞
Mike Vine
11/13/2023
我唯一能看到的另一件事可能是一个问题,您可能处于尝试通过析构函数加入线程的情况。这会很糟糕。Acqer
评论