线程不在 Linux 上终止,但在 Mac 上终止
Threads not terminating on Linux but on Mac
我目前正在研究一种遗传算法,其中使用不同的独立线程计算新种群。我的程序在 OSX 上运行良好,但某些线程在 Linux 机器上不会终止。
我有以下方法,每个线程都会执行该方法,直到我生成了足够的个人。我正在使用一个互斥锁,它是人口类的一部分(因为这种方法就是这样)。因此,互斥对象不是静态的。该方法传递一组parents
它可以在第一个parents_max
的父母身上选择一个来生成一个新的孩子。子项是由另一个父对象突变或重组产生的。在select_randomly
和bool_with_prob
中,我使用了来自<random>
的几个分布(所有局部变量)来选择一个随机父级或为我提供一个随机布尔值。
我在互联网上搜索了线程不会终止的原因,并在使用std::random_device
或std::mt19937
对象的方法周围添加了服务器(可能是不必要的)锁。
void generate_childs(std::set<individual> &parents, double mutation_rate, size_t parents_max)
{
size_t individuals_size;
{
boost::lock_guard<boost::mutex> lock(mutex);
individuals_size = individuals.size();
}
auto selectable_parents_end = parents.begin();
std::advance(selectable_parents_end, parents_max);
while(individuals_size < size)
{
mutex.lock();
individual male = *utilities::container::select_randomly(parents.begin(), selectable_parents_end);
bool generate_child = utilities::container::bool_with_prob(0.3);
mutex.unlock();
boost::optional<individual> ind;
if(generate_child)
{
mutex.lock();
individual female = *utilities::container::select_randomly(parents.begin(), parents.end());
mutex.unlock();
ind = mutation::combined_mutated_child(male, female, mutation_rate);
} else
{
ind = mutation::mutated_child(male, 0.9);
}
if(ind && ind->is_valid())
{
boost::lock_guard<boost::mutex> lock(mutex);
if (individuals.size() < size) {
individuals.insert(*ind);
}
}
{
boost::lock_guard<boost::mutex> lock(mutex);
individuals_size = individuals.size();
}
}
}
我像这样启动线程:
unsigned int number_of_threads = std::thread::hardware_concurrency();
auto parents = individuals;
std::vector<boost::thread> threads;
for(size_t i = 0; i<number_of_threads; i++)
{
threads.emplace_back(&population::generate_childs,
this,
std::ref(parents),
mutation_rate,
parents_max);
}
for(auto &t: threads)
{
t.join();
std::cout << "Thread finished" << individuals.size() << std::endl;
}
在使用 Clang 编译的本地 (OSX) 机器上执行我的程序时,它按预期执行。在我的 Linux 机器上,它没有完成。我什至尝试设置number_of_threads=1
,但没有帮助。当程序在我的 Linux 机器上没有终止时,我无法通过Ctrl+C
退出它。我可能遇到竞争条件或死锁的任何想法?
编辑
按照建议,我打印了一个注释,其中包含每个线程的线程 ID。显然,我在更新大小时使用锁是不合适的。因此,我修改了最后一个锁,如下所示:
std::cout << i << " updating size" << std::endl;
{
std::cout << i << " updating size about to lock" << std::endl;
boost::lock_guard<boost::mutex> lock(configuration::mutex);
std::cout << i << " updating size about to locked" << std::endl;
individuals_size = individuals.size();
if(individuals_size >= size)
{
std::cout << i << " returning" << std::endl;
return;
}
}
我的程序的输出是这样的(跳过了线程工作正常的部分):
0 started
2 started
3 started
3 entered while
0 entered while
1 started
2 entered while
1 entered while
3 got male 1
0 got male 0
3 got female
2 got male 1
1 got male 1
2 got female
1 got female
0 got mutated
0 before is valid
0 inserting
0 inserted
0 updating size
0 updating size about to lock
0 updating size about to locked
0 returning
Thread finished10
2 got combined
2 before is valid
2 inserting
2 inserted
2 updating size
2 updating size about to lock
2 updating size about to locked
2 returning
在此之后,我没有得到任何额外的输出。对我来说,锁罩似乎不会释放互斥锁。是我加入线程的顺序吗?因为我尝试在线程 1 之前加入线程 2,即使它还没有完成?
我不喜欢你的代码中的一件事是你滥用了锁。例如,当您检索容器的大小时,您无法确定刚刚检索的大小在解锁互斥锁后是正确的。因此,正确的模式可能是锁定您检索大小的代码块并使用容器,假设此大小是正确的 - 并在不再需要此容器时解锁它。
因此,您应该重新设计代码,因为许多地方可能存在竞争条件。您的问题的一个可能答案,请查看下面的代码:
mutex.lock();
individual male = *utilities::container::select_randomly(parents.begin(), selectable_parents_end);
bool generate_child = utilities::container::bool_with_prob(0.3);
mutex.unlock();
什么是select_randomly
中抛出的异常?您永远不会解锁互斥锁,这是一个死锁条件。为什么它会引发异常?例如,由于争用条件,值selectable_parents_end
已过时。
- 代码在main()中运行,但在函数中出现错误
- 链接阶段在Ubuntu上失败,但在MacOS上失败
- 对C宏的未定义引用,但在定义它时会出现重新定义错误
- c++17文件系统::recursive_directory迭代器()在mac上没有给出这样的目录,但在windows上
- 断言中的Fold表达式在某些计算机上编译,但在其他计算机上不编译
- 换位表导致测试失败(但在游戏中运行良好)
- 库标题在标题中不可见,但在 cmake build 下.cpp文件中完全可见.为什么?
- 树莓上的 Libtorch 无法加载 pt 文件,但在 ubuntu 上工作
- 在成员dynamic_bitset上使用 boost::from_block_range 时出错,但在本地dynamic
- 编译在我的 Mac 上工作,但在集群 (Linux) 上不起作用
- 我编写了代码将十进制分数转换为其二进制等效数.它编译得很好,但在执行时挂起
- 我的代码运行良好,但在游戏循环中中断
- C++ assigment std::list:<typename>:itrator 在 main 中工作,但在方法中它不起作用
- C++代码在台式机上工作正常,但在笔记本电脑上则不行
- 实现 DFS 在较短的输入下工作正常,但在较大的输入下会抛出分段错误
- 点云库在VS 2019中不起作用,但在VS 2017中确实有效
- 线程不在 Linux 上终止,但在 Mac 上终止
- 从 eclipse IDE 运行工作正常,但在从终端运行时终止
- 为什么我的 c++ 程序在 Eclipse 中没有输出而终止,但在 Visual Studio 中工作
- For 循环结束自身并终止正在运行的程序,但在删除斜率计算语句时正常运行