c++ - 如果语句仅在调试 cout 行之前通过(C 中的多线程)
问题描述
我创建了这段代码,用于实时解决 CPU 密集型任务,并可能作为未来游戏引擎的基础。为此,我创建了一个系统,其中每个线程都会修改一个整数数组,以指示它们是否已完成当前任务。
使用超过 4 个线程运行它时会出现问题。当使用 6 个或更多线程时,“if (threadone_private == threadcount)”停止工作,除非我添加了这个调试行“cout << threadone_private << endl;” 在它之前。
我无法理解为什么此调试行对 if 条件函数是否按预期产生任何影响,也无法理解为什么在使用 4 个或更少线程时没有它也能工作。
对于此代码,我正在使用:
#include <GL/glew.h>
#include <GLFW/glfw3.h>
#include <iostream>
#include <thread>
#include <atomic>
#include <vector>
#include <string>
#include <fstream>
#include <sstream>
using namespace std;
目前这段代码最多只能计算到 60 万亿,异步步长为 30 亿,非常快。
以下是代码的相关部分:
int thread_done[6] = { 0,0,0,0,0,0 };
atomic<long long int> testvar1 = 0;
atomic<long long int> testvar2 = 0;
atomic<long long int> testvar3 = 0;
atomic<long long int> testvar4 = 0;
atomic<long long int> testvar5 = 0;
atomic<long long int> testvar6 = 0;
void task1(long long int testvar, int thread_number)
{
int continue_work = 1;
for (; ; ) {
while (continue_work == 1) {
for (int i = 1; i < 3000000001; i++) {
testvar++;
}
thread_done[thread_number] = 1;
if (thread_number==0) {
testvar1 = testvar;
}
if (thread_number == 1) {
testvar2 = testvar;
}
if (thread_number == 2) {
testvar3 = testvar;
}
if (thread_number == 3) {
testvar4 = testvar;
}
if (thread_number == 4) {
testvar5 = testvar;
}
if (thread_number == 5) {
testvar6 = testvar;
}
continue_work = 0;
}
if (thread_done[thread_number] == 0) {
continue_work = 1;
}
}
}
这是主线程的相关部分:
int main() {
long long int testvar = 0;
int threadcount = 6;
int threadone_private = 0;
thread thread_1(task1, testvar, 0);
thread thread_2(task1, testvar, 1);
thread thread_3(task1, testvar, 2);
thread thread_4(task1, testvar, 3);
thread thread_5(task1, testvar, 4);
thread thread_6(task1, testvar, 5);
for (; ; ) {
if (threadcount == 0) {
for (int i = 1; i < 3000001; i++) {
testvar++;
}
cout << testvar << endl;
}
else {
while (testvar < 60000000000000) {
threadone_private = thread_done[0] + thread_done[1] + thread_done[2] + thread_done[3] + thread_done[4] + thread_done[5];
cout << threadone_private << endl;
if (threadone_private == threadcount) {
testvar = testvar1 + testvar2 + testvar3 + testvar4 + testvar5 + testvar6;
cout << testvar << endl;
thread_done[0] = 0;
thread_done[1] = 0;
thread_done[2] = 0;
thread_done[3] = 0;
thread_done[4] = 0;
thread_done[5] = 0;
}
}
}
}
}
我希望因为每个工作线程只修改数组threadone_private中的一个int,并且由于主线程只在所有工作线程都等待之前读取它,所以这个if(threadone_private == threadcount)应该是防弹的......显然我'我错过了一些重要的东西,每当我改变它时就会出错:
threadone_private = thread_done[0] + thread_done[1] + thread_done[2] + thread_done[3] + thread_done[4] + thread_done[5];
cout << threadone_private << endl;
if (threadone_private == threadcount) {
对此:
threadone_private = thread_done[0] + thread_done[1] + thread_done[2] + thread_done[3] + thread_done[4] + thread_done[5];
//cout << threadone_private << endl;
if (threadone_private == threadcount) {
解决方案
免责声明:并发代码非常复杂且容易出错,因此使用更高级别的抽象通常是个好主意。有很多细节很容易在没有注意到的情况下出错。如果您不是专家,您应该非常仔细地考虑进行此类低级编程。遗憾的是,C++ 缺乏良好的内置高级并发构造,但有一些库可以处理这个问题。
目前还不清楚整个代码应该对我做什么。据我所知,代码是否停止完全依赖于时间——即使你正确地进行了同步——这完全是不确定的。您的线程可以以一种thread_done
永远不会完全正确的方式执行。
但除此之外,至少还有一个正确性问题:您在int thread_done[6] = { 0,0,0,0,0,0 };
没有同步的情况下进行读写。这是未定义的行为,因此编译器可以做它想做的事。
可能发生的情况是编译器看到它可以缓存 的值,threadone_private
因为线程从不写入它,因此该值不能改变(合法地)。外部调用std::cout
意味着它不能确定值不会在其背后发生变化,因此它必须在每次迭代新的时候读取值(std::cout 也使用锁,这在大多数实现中会导致同步,这再次限制了编译器可以假设)。
推荐阅读
- android - How to create handler with callbacks that run on a different thread?
- python - 从日期列表中使用 Pandas (DateOffset) 创建日历
- css - 如何将 DIV 与其容器底部对齐?
- python - 蟒蛇:名称错误:名称
- ionic3 - 如何在ionic3中调用没有表单数据的POST API?
- javascript - Cordova 中的 URL 添加了感叹号
- android - Lottie 动画编译不工作 - 为什么?
- apache-spark - 写入外部 Hive 表时的 Spark 压缩
- java - Java并发 - 线程未完成循环
- symfony - 没有斜杠的 Twig 命名空间路径在本地计算机(Mac)上有效,但在服务器上无效