c++ - 在另一个线程中独立计时 For 循环的每个滴答声的最佳方法
问题描述
假设我有一个客户端线程和一个服务器线程。客户端线程必须执行昂贵的 for 循环操作,这很容易挂起。这样,服务器就可以独立判断for循环的每个tick是否超过了最大时间。这背后的背景是,如果完成一个滴答的时间太长,服务器将使客户端超时。
我最初的想法是在客户端和服务器线程中有两个 for 循环。服务器线程将有一个等待 1 秒的条件变量。如果客户端没有在每个tick的1秒内通知条件变量,服务器将超时:
服务器
bool success;
for (int i = 0; i < 10; i++) {
std::unique_lock<std::mutex> lock(CLIENT_MUTEX);
success = CLIENT_CV.wait_for(lock, std::chrono::seconds(1));
if (!success) {
std::cout << "timed out during tick " << i << std::endl;
break;
}
}
客户
for (int i = 0; i < 10; i++) {
std::unique_lock<std::mutex> lock(CLIENT_MUTEX);
//do work
CLIENT_CV.notify_one();
}
然而,我的实现尝试是不可靠的,并且在给客户相同的工作的情况下随机超时。如何改进设计以使其更可靠?
边注:
一个简单的解决方案是让服务器对整个 for 循环而不是每个滴答计时。但是,如果 for 循环在 10 次中的第 1 次失败,并且计时器正在等待 10 秒,则将在 10 秒后通知客户端。但是,如果服务器对每个滴答(10x1sec = 10 秒)施加 1 秒超时,则客户端将被通知超时,而无需等待整整 10 秒。
编辑。
整个客户端/服务器/超时的类比只是将问题置于上下文中。我纯粹对从不同线程计时 for 循环的最佳方法感兴趣。
解决方案
这样做的一种方法可能是:
共享变量:
std::vector<std::chrono::time_point<std::chrono::high_resolution_clock>> ledger;
std::mutex ledger_mtx;
客户:
for (int i = 0; i < 10; i++) {
{
std::scoped_lock lock(ledger_mtx);
ledger.push_back(std::chrono::high_resolution_clock::now());
}
// Do work
}
{
std::scoped_lock lock(ledger_mtx);
ledger.push_back(std::chrono::high_resolution_clock::now());
}
服务器:
size_t id = 0;
std::this_thread::wait_for(1s); // Some time so that initial write to ledger is made
while(true) {
{
std::scoped_lock lock(ledger_mtx);
if(ledger.size()==id) { /* Do something if the thread hangs */ }
id = ledger.size();
std::chrono::time_point<std::chrono::high_resolution_clock> last_tick = ledger.back();
}
if(id == 11) break;
std::this_thread::sleep_for(1s - (std::chrono::high_resolution_clock::now() - last_tick));
}
这样您就可以对线程进行计时,同时从外部对其进行监控。这是最好的方法吗?可能不会,但它确实为您提供了所需的时间。
推荐阅读
- python - Python 创建一个对类的冗余引用
- visual-studio-code - 这个粉红色在我的 VScode 树视图中代表什么
- etl - 使用 informatica 在目标中插入更新和删除源标志记录
- php - 在模型方法中创建条件
- r - 在 dplyr 中选择不同的行
- python - 如何对元组的字典值进行排序
- docker - 如何使 HDFS 在 docker swarm 中工作
- javascript - 在javascript中使用牛津词典API时的禁止请求状态
- javascript - 删除具有相同类的两个元素之一
- javascript - 动作被传递给状态对象,动作对象为空