c++ - 自定义节流器中的无限循环场景(竞争条件?)
问题描述
当某些客户端(正在进行外部调用)出现退避异常并且需要在进行另一个 API 调用之前休眠时,我编写了一个自定义节流器来处理场景。
我有一个带有奇怪场景的内存转储:卡在无限循环中,尽管我看不出有什么原因。此应用程序有许多线程,并且所有客户端调用都使用以下代码进行限制。对某些 API 的调用是这样完成的:
bool res = DoSomeAction([&]{ /* call client m_client.callAPI()*/ return true}
内存转储显示只有 1 个线程在工作(通常有 10 个),并且 m_isThrottling 设置为 true,因此整个应用程序一直在运行。
这种情况怎么会发生?有什么更好的实现建议(带有 m_ 前缀的变量意味着类变量,m_throttlingTime 和 m_isThrottling 是静态类变量)?
template<typename T>
bool ThrottlerClass::DoSomeAction(T && lambda)
{
for (int retriesCount = 3; retriesCount > 0; --retriesCount)
{
while (m_isThrottling) //dump is stuck here
{
Sleep(10000);
}
try
{
return lambda();
}
catch (const std::exception& ex)
{
int time = m_client->GetThrottlingTimeMS(); //the client got exception making API call and saves it
if (time > 0)
{
ExclusiveLock lock(&m_throttlingMutex); //custom scope mutex
m_isThrottling = true;
if (time > m_throttlingTime)
m_throttlingTime = time;
}
if (m_throttlingTime > 0)
{
Sleep(m_throttlingTime);
{
ExclusiveLock lock(&m_throttlingMutex);
m_isThrottling = false;
m_throttlingTime = 0;
}
}
continue;
}
}
return false;
}
解决方案
无法保证m_isTrhottling
您的线程中的值将永远获得其真实值。事实上,每个线程都有自己的世界观,因此在写入 的另一个线程的视图中m_isThrottling
,值是true
,但您的第三个看到的是不同的画面。
锁是线程世界观同步的一种方式。如果您使用锁而不是循环,则该值将在您的等待线程中更新。
使固定 :
- 要么使用锁
- 或者
std::atomic<bool>
这也保证了同步。
澄清编辑:类变量上下文中的关键字static
与内存模型无关。在这种情况下,关键字只是说明变量属于类而不属于任何特定对象。这与线程的世界观(或缺少)的同步完全无关。与线程相关的唯一地方static
是函数内部的静态变量初始化,但事实并非如此(函数静态变量和初始化都不是)
推荐阅读
- angular - Angular如何在QueryList中找到哪个元素
被点击 - python - 是否有在 Python 中动态添加 Microsoft Word 脚注的解决方法?
- php - 如何将数据从下拉列表发布到 PHP 中的过滤表?
- google-apps-script - 我制作了一个谷歌应用程序脚本,我想在自己的域中共享但不发布到网络上?
- excel - Excel列表中的模糊查找是否垂直而不是水平匹配表?
- cobol - 您如何比较多个字符串以查找重复项?
- python - 将记录器消息存储在列表中
- c - 如何计算给定字符串中每个单词的单词总数和字符数并创建一维数组?
- angular - 从 6 到 7 的角度迁移后无法比较茉莉花中的枚举
- javascript - 如何使 Three.js FOV 响应高度和宽度?