- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
我正在尝试将线程合并到我的项目中,但遇到一个问题,即仅使用 1 个工作线程就会使其永久“休眠”。也许我有竞态条件,只是没注意到。
我的PeriodicThreads
对象维护一个线程集合。一旦 PeriodicThreads::exec_threads()
被调用,线程就会被通知、被唤醒并执行它们的任务。之后,他们又睡着了。
这样一个工作线程的功能:
void PeriodicThreads::threadWork(size_t threadId){
//not really used, but need to decalre to use conditional_variable:
std::mutex mutex;
std::unique_lock<std::mutex> lck(mutex);
while (true){
// wait until told to start working on a task:
while (_thread_shouldWork[threadId] == false){
_threads_startSignal.wait(lck);
}
thread_iteration(threadId); //virtual function
_thread_shouldWork[threadId] = false; //vector of flags
_thread_doneSignal.notify_all();
}//end while(true) - run until terminated externally or this whole obj is deleted
}
如您所见,每个线程都在监视标志 vector 中自己的条目,一旦发现它的标志为真 - 执行任务,然后重置其标志。
这里是可以唤醒所有线程的函数:
std::atomic_bool _threadsWorking =false;
//blocks the current thread until all worker threads have completed:
void PeriodicThreads::exec_threads(){
if(_threadsWorking ){
throw std::runtime_error("you requested exec_threads(), but threads haven't yet finished executing the previous task!");
}
_threadsWorking = true;//NOTICE: doing this after the exception check.
//tell all threads to unpause by setting their flags to 'true'
std::fill(_thread_shouldWork.begin(), _thread_shouldWork.end(), true);
_threads_startSignal.notify_all();
//wait for threads to complete:
std::mutex mutex;
std::unique_lock<std::mutex> lck(mutex); //lock & mutex are not really used.
auto isContinueWaiting = [&]()->bool{
bool threadsWorking = false;
for (size_t i=0; i<_thread_shouldWork.size(); ++i){
threadsWorking |= _thread_shouldWork[i];
}
return threadsWorking;
};
while (isContinueWaiting()){
_thread_doneSignal.wait(lck);
}
_threadsWorking = false;//set atomic to false
}
调用 exec_threads()
可以正常进行数百次或在极少数情况下数千次连续迭代。调用发生在主线程的 while
循环中。它的工作线程处理任务,重置其标志并返回休眠状态,直到下一个 exec_threads()
,依此类推。
然而,一段时间后,程序突然进入“休眠”状态,似乎暂停了,但并没有崩溃。
在这种“休眠”期间,在我的 condition_variables 的任何 while-loop
处放置一个断点实际上不会导致触发该断点。
我偷偷摸摸地创建了自己的验证线程(与 main
并行)并监视我的 PeriodicThreads
对象。当它进入休眠状态时,我的验证线程不断向控制台输出当前没有线程正在运行(PeriodicThreads
的 _threadsWorking
原子永久设置为 false)。然而,在其他测试期间,一旦“休眠问题”开始,原子将保持为 true
。
奇怪的是,如果我强制 PeriodicThreads::run_thread
在重置其标志之前至少休眠 10 微秒,一切都会正常进行,并且不会发生“休眠”。否则,如果我们允许线程非常快速地完成它的任务,它可能会导致整个问题。
我将每个 condition_variable
包装在一个 while 循环中,以防止虚假唤醒触发转换,以及 .wait()< 之前调用
被调用。 Link notify_all
的情况
注意,即使我只有 1 个工作线程也会发生这种情况
可能是什么原因?
编辑
放弃这些 vector 标志并仅在具有 1 个工作线程的单个 atomic_bool
上进行测试仍然显示相同的问题。
最佳答案
所有共享数据都应由互斥锁保护。互斥量应该(至少)与共享数据具有相同的范围。
您的_thread_shouldWork
容器是共享数据。您可以创建一个全局互斥锁数组,每个互斥锁都可以保护自己的 _thread_shouldWork
元素。 (见下面的注释)。您还应该至少拥有与互斥量一样多的条件变量。 (您可以将 1 个互斥量与多个不同的条件变量一起使用,但不应将多个不同的互斥量与 1 个条件变量一起使用。)
condition_variable
应该保护实际 条件(在这种情况下,_thread_shouldWork
的单个元素在任何给定点的状态)和互斥量用于保护包含该条件的变量。
如果您只是使用一个随机的本地互斥量(就像您在线程代码中那样)或者根本不使用互斥量(在主代码中),那么所有的赌注都没有了。这是未定义的行为。尽管我大部分时间都能看到它(幸运地)工作。我怀疑正在发生的事情是工作线程缺少来自主线程的信号。也可能是您的主线程缺少来自工作线程的信号。 (线程A读取状态进入while
循环,然后线程B改变状态发送通知,然后线程A进入休眠状态...等待已经发送的通知)
具有本地作用域的互斥体是一个危险信号!
注意:如果您使用的是 vector ,则必须小心,因为添加或删除项目会触发调整大小,这将触及元素而无需先获取互斥量(因为 vector 当然不知道您的互斥量) .
使用数组时还必须注意错误共享
编辑:这是 @Kari 发现的一段视频,对解释虚假分享很有用 https://www.youtube.com/watch?v=dznxqe1Uk3E
关于c++ - 执行速度太快后,工作线程永久休眠,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/52435800/
我有一个“有趣”的问题,即以两种不同的方式运行 wine 会导致: $> wine --version /Applications/Wine.app/Contents/Resources/bin/wi
我制作了这个网络抓取工具来获取网页中的表格。我使用 puppeteer (不知道 crontab 有问题)、Python 进行清理并处理数据库的输出 但令我惊讶的是,当我执行它时 */50 * * *
JavaScript 是否被调用或执行取决于什么?准确地说,我有两个函数,它们都以相同的方式调用: [self.mapView stringByEvaluatingJavaScriptFromStri
我目前正在使用 python 做一个机器学习项目(这里是初学者,从头开始学习一切)。 只是想知道 statsmodels 的 OLS 和 scikit 的 PooledOlS 使用我拥有的相同面板数据
在使用集成对象模型 (IOM) 后,我可以执行 SAS 代码并将 SAS 数据集读入 .Net/C# 数据集 here . 只是好奇,使用 .Net 作为 SAS 服务器的客户端与使用 Enterpr
有一些直接的 jQuery 在单击时隐藏打开的 div 未显示,但仍将高度添加到导航中以使其看起来好像要掉下来了。 这个脚本工作正常: $(document).ready(funct
这个问题已经有答案了: How do I compare strings in Java? (23 个回答) 已关闭 4 年前。 这里是 Java 新手,我正在使用 NetBeans 尝试一些简单的代
如果我将它切换到 Python 2.x,它执行 10。这是为什么? 训练逻辑回归模型 import keras.backend as
我有两个脚本,它们包含在 HTML 正文中。在第一个脚本中,我初始化一个 JS 对象,该对象在第二个脚本标记中引用。 ... obj.a = 1000; obj.
每当我运行该方法时,我都会收到一个带有数字的错误 以下是我的代码。 public String getAccount() { String s = "Listing the accounts";
我已经用 do~while(true) 创建了我的菜单;但是每次用户输入一个数字时,它不会运行程序,而是再次显示菜单!你怎么看? //我的主要方法 public static void main(St
执行命令后,如何让IPython通知我?我可以使用铃声/警报还是通过弹出窗口获取它?我正在OS X 10.8.5的iTerm上运行Anaconda。 最佳答案 使用最新版本的iTerm,您可以在she
您好,我刚刚使用菜单栏为 Swing 编写了代码。但是问题出现在运行中。我输入: javac Menu.java java Menu 它没有给出任何错误,但 GUI 没有显示。这是我的源代码以供引用:
我觉得这里缺少明显的东西,但是我看不到它写在任何地方。 我使用Authenticode证书对可执行文件进行签名,但是当我开始学习有关它的更多信息时,我对原样的值(value)提出了质疑。 签名的exe
我正在设计一个应用程序,它使用 DataTables 中的预定义库来创建数据表。我想对数据表执行删除操作,为此应在按钮单击事件上执行 java 脚本。 $(document).ready(functi
我是 Haskell 新手,如果有人愿意帮助我,我会很高兴!我试图让这个程序与 do while 循环一起工作。 第二个 getLine 命令的结果被放入变量 goGlenn 中,如果 goGlenn
我有一个用 swing 实现迷你游戏的程序,在主类中我有一个循环,用于监听游戏 map 中的 boolean 值。使用 while 实现的循环不会执行一条指令,如果它是唯一的一条指令,我不知道为什么。
我正在尝试开发一个连接到 Oracle 数据库并执行函数的 Java 应用程序。如果我在 Eclipse 中运行该应用程序,它可以工作,但是当我尝试在 Windows 命令提示符中运行 .jar 时,
我正在阅读有关 Java 中的 Future 和 javascript 中的 Promises 的内容。下面是我作为示例编写的代码。我的问题是分配给 future 的任务什么时候开始执行? 当如下行创
我有一个常见的情况,您有两个变量(xSpeed 和 ySpeed),当它们低于 minSpeed 时,我想将它们独立设置为零,并在它们都为零时退出。 最有效的方法是什么?目前我有两种方法(方法2更干净
我是一名优秀的程序员,十分优秀!