我有两个函数,一个是运行serveRunForever,另一个是shutDown。
Server::runForever ()
{
while(!doStop_)
{
unique_lock<mutex> lck(stop);
//Do something, it should be looping in while loop
CV.wait(lck, [this]() {return doStop_;});
}
上面不是循环它开始在 CV.wait() 中等待。
Server::shutDown()
{
scoped_lock lck(stop);
doStop_ = true;
CV.notify_one();
}
runForever 不在 while 中循环,我想连续循环直到调用关闭。帮我解决这个问题。我非常感谢对此的任何线索和建议。
最佳答案
第 1 部分
我对您的程序进行了修改,使其现在可以运行。主要是我必须使用 doStop_ = true;
而不是 doStop_ = false;
,因为根据英语程序的逻辑,当 do-stop 变为 true 时应该停止。
此外,您还必须按照我在下面的代码中所示的方式放置互斥锁,即第一个锁位于 while 循环之外,第二个标志设置锁的范围应位于通知调用之外。事实上,如果您将 wait
与谓词一起使用,则实际上不需要 while 循环,如 std docs 中所述。 .
下面是工作过程的模拟:
#include <condition_variable>
#include <thread>
#include <mutex>
#include <iostream>
#include <chrono>
class Server {
public:
void runForever();
void shutDown();
private:
std::condition_variable CV;
std::mutex stop;
bool doStop_ = false;
};
void Server::runForever() {
std::unique_lock<std::mutex> lck(stop);
while (!doStop_)
CV.wait(lck, [this]() { return doStop_; });
}
void Server::shutDown() {
{
std::lock_guard<std::mutex> lck(stop);
doStop_ = true;
}
CV.notify_one();
}
int main() {
auto const time_begin = std::chrono::high_resolution_clock::now();
auto TimeElapsed = [&]{
return double(std::chrono::duration_cast<std::chrono::milliseconds>(
std::chrono::high_resolution_clock::now() - time_begin).count()) / 1000;
};
Server server;
std::this_thread::sleep_for(std::chrono::milliseconds(200));
std::thread t0([&]{
std::cout << "Server started at " << TimeElapsed() << " sec" << std::endl;
server.runForever();
std::cout << "Server stopped at " << TimeElapsed() << " sec" << std::endl;
});
std::this_thread::sleep_for(std::chrono::milliseconds(1500));
server.shutDown();
t0.join();
}
输出:
Server started at 0.2 sec
Server stopped at 1.7 sec
第 2 部分
如果您需要在 while 循环内进行一些计算,而不仅仅是等待,那么条件变量不适合您。您应该使用 std::atomic bool相反,或者只是普通的 bool 值也几乎足够了。原子允许立即传播 bool 变量的更改值。请参阅下面的代码:
#include <atomic>
#include <thread>
#include <mutex>
#include <iostream>
#include <chrono>
class Server {
public:
void runForever();
void shutDown();
private:
std::atomic<bool> doStop_ = false;
};
void Server::runForever() {
while (!doStop_) {
std::cout << "Doing computation..." << std::endl;
std::this_thread::sleep_for(std::chrono::milliseconds(200));
}
}
void Server::shutDown() {
doStop_ = true;
}
int main() {
auto const time_begin = std::chrono::high_resolution_clock::now();
auto TimeElapsed = [&]{
return double(std::chrono::duration_cast<std::chrono::milliseconds>(
std::chrono::high_resolution_clock::now() - time_begin).count()) / 1000;
};
Server server;
std::this_thread::sleep_for(std::chrono::milliseconds(200));
std::thread t0([&]{
std::cout << "Server started at " << TimeElapsed() << " sec" << std::endl;
server.runForever();
std::cout << "Server stopped at " << TimeElapsed() << " sec" << std::endl;
});
std::this_thread::sleep_for(std::chrono::milliseconds(900));
server.shutDown();
t0.join();
}
输出:
Server started at 0.21 sec
Doing computation...
Doing computation...
Doing computation...
Doing computation...
Doing computation...
Server stopped at 1.21 sec
第三部分
还可以与atomic bool一起使用while循环内的条件变量来将其用于暂停目的,而不是std::this_thread::sleep_for()
。
条件变量将有助于停止前的最后一次迭代,有助于在整个暂停完成之前提前终止。
您可以在下面的控制台输出示例中看到,与第 2 部分示例中的 1.2 秒
相比,服务器在 1.1 秒
处提前停止强>我的回答。
#include <condition_variable>
#include <atomic>
#include <thread>
#include <mutex>
#include <iostream>
#include <chrono>
class Server {
public:
void runForever();
void shutDown();
private:
std::atomic<bool> doStop_ = false;
std::mutex mutex_;
std::condition_variable CV;
};
void Server::runForever() {
while (!doStop_) {
std::cout << "Doing computation..." << std::endl;
std::unique_lock<std::mutex> lck(mutex_);
CV.wait_for(lck, std::chrono::milliseconds(200),
[this]{ return bool(doStop_); });
}
}
void Server::shutDown() {
{
std::lock_guard<std::mutex> lck(mutex_);
doStop_ = true;
}
CV.notify_all();
}
int main() {
auto const time_begin = std::chrono::high_resolution_clock::now();
auto TimeElapsed = [&]{
return double(std::chrono::duration_cast<std::chrono::milliseconds>(
std::chrono::high_resolution_clock::now() - time_begin).count()) / 1000;
};
Server server;
std::this_thread::sleep_for(std::chrono::milliseconds(200));
std::thread t0([&]{
std::cout << "Server started at " << TimeElapsed() << " sec" << std::endl;
server.runForever();
std::cout << "Server stopped at " << TimeElapsed() << " sec" << std::endl;
});
std::this_thread::sleep_for(std::chrono::milliseconds(900));
server.shutDown();
t0.join();
}
输出:
Server started at 0.203 sec
Doing computation...
Doing computation...
Doing computation...
Doing computation...
Doing computation...
Server stopped at 1.1 sec
关于c++ - 如何在 while 循环中使用条件变量进行互斥锁?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/69971693/