C++ If语句仅在前面有debug cout行时通过(C中的多线程)
我创建了这段代码,用于实时解决CPU密集型任务,并可能作为未来游戏引擎的基础。为此,我创建了一个系统,其中有一个int数组,每个线程都会修改该数组,以表示它们是否完成了当前任务C++ If语句仅在前面有debug cout行时通过(C中的多线程),c++,multithreading,C++,Multithreading,我创建了这段代码,用于实时解决CPU密集型任务,并可能作为未来游戏引擎的基础。为此,我创建了一个系统,其中有一个int数组,每个线程都会修改该数组,以表示它们是否完成了当前任务 使用4个以上的线程运行时会出现问题。当使用6个或更多线程时,除非添加此调试行,否则“if(threadone\u private==threadcount)”将停止工作“cout我在代码中看不到任何std::mutex、std::condition\u变量或std::lock的变体。如果没有以上任何一项,则执行多线程将永
使用4个以上的线程运行时会出现问题。当使用6个或更多线程时,除非添加此调试行,否则“if(threadone\u private==threadcount)”将停止工作“cout我在代码中看不到任何std::mutex、std::condition\u变量或std::lock的变体。如果没有以上任何一项,则执行多线程将永远不会可靠地成功。因为每当多个线程修改同一数据时,您需要确保在任何给定时间只有一个线程(包括主线程)可以访问该数据 编辑:我注意到你使用原子。我没有这方面的任何经验,但是我知道使用互斥可以可靠地工作 因此,您需要使用如下互斥锁锁定对该数据的每次访问(读或写):
//somewhere
std::mutex myMutex;
std::condition_variable myCondition;
int workersDone = 0;
/* main thread */
createWorkerThread1();
createWorkerThread2();
{
std::unique_lock<std::mutex> lock(myMutex); //waits until mutex is locked.
while(workersDone != 2) {
myCondition.wait(lock); //the mutex is unlocked while waiting
}
std::cout << "the data is ready now" << std::endl;
} //the lock is destroyed, unlocking the mutex
/* Worker thread */
while(true) {
{
std::unique_lock<std::mutex> lock(myMutex); //waits until mutex is locked
if(read_or_modify_a_piece_of_shared_data() == DATA_FINISHED) {
break; //lock leaves the scope, unlocks the mutex
}
}
prepare_everything_for_the_next_piece_of_shared_data(); //DO NOT access data here
}
//data is processed
++workersDone;
myCondition.notify_one(); //no mutex here. This wakes up the waiting thread
//某处
std::mutex myMutex;
std::条件变量真菌病;
int workersDone=0;
/*主线*/
createWorkerThread1();
createWorkerThread2();
{
std::unique_lock lock(myMutex);//等待直到锁定互斥锁。
while(workersDone!=2){
myCondition.wait(lock);//在等待时,互斥锁被解锁
}
std::cout我在代码中看不到任何std::mutex、std::condition\u变量或std::lock的变体。如果没有这些变量,则执行多线程处理将永远不会可靠地成功。因为每当多个线程修改同一数据时,您需要确保在任何给定时间只有一个线程(包括主线程)可以访问该数据
编辑:我注意到你使用了原子。我没有这方面的经验,但我知道使用互斥锁工作可靠
因此,您需要使用如下互斥锁锁定对该数据的每次访问(读或写):
//somewhere
std::mutex myMutex;
std::condition_variable myCondition;
int workersDone = 0;
/* main thread */
createWorkerThread1();
createWorkerThread2();
{
std::unique_lock<std::mutex> lock(myMutex); //waits until mutex is locked.
while(workersDone != 2) {
myCondition.wait(lock); //the mutex is unlocked while waiting
}
std::cout << "the data is ready now" << std::endl;
} //the lock is destroyed, unlocking the mutex
/* Worker thread */
while(true) {
{
std::unique_lock<std::mutex> lock(myMutex); //waits until mutex is locked
if(read_or_modify_a_piece_of_shared_data() == DATA_FINISHED) {
break; //lock leaves the scope, unlocks the mutex
}
}
prepare_everything_for_the_next_piece_of_shared_data(); //DO NOT access data here
}
//data is processed
++workersDone;
myCondition.notify_one(); //no mutex here. This wakes up the waiting thread
//某处
std::mutex myMutex;
std::条件变量真菌病;
int workersDone=0;
/*主线*/
createWorkerThread1();
createWorkerThread2();
{
std::unique_lock lock(myMutex);//等待直到锁定互斥锁。
while(workersDone!=2){
myCondition.wait(lock);//在等待时,互斥锁被解锁
}
STD::CUT< P>免责声明:并发代码非常复杂,容易出错,所以使用高级抽象通常是一个好主意。有很多细节很容易出错,而不必注意。如果你不是专家,你应该非常仔细地考虑做这样的低级编程。C++很不好。内置的高级并发构造,但是有一些库可以处理这个问题
现在还不清楚整个代码到底应该对我做什么。就我所知,代码是否会停止完全依赖于时间——即使你正确地进行了同步——这是完全不确定的。你的线程可以以这样一种方式执行,thread\u done
永远都不是真的
但除此之外,至少还有一个正确性问题:在没有同步的情况下,您正在读取和写入int-thread_-done[6]={0,0,0,0,0};
。这是未定义的行为,因此编译器可以执行它想要的操作
可能发生的情况是,编译器看到它可以缓存threadone\u private
的值,因为线程从未写入该值,因此该值不能更改(合法)。对std::cout
的外部调用意味着它不能确定该值在背后没有更改,因此它必须在每次新的迭代中读取该值(另外,std::cout在大多数实现中使用锁,这会导致同步,这又限制了编译器的假设)虽然C++并发代码很复杂,容易出错,但使用高级抽象是一个好主意。有很多细节都很容易出错,如果你不是专家,你应该非常仔细地考虑做这样的低级编程。-在高级并发构造中,但是有一些库可以处理这个问题
现在还不清楚整个代码到底应该对我做什么。就我所知,代码是否会停止完全依赖于时间——即使你正确地进行了同步——这是完全不确定的。你的线程可以以这样一种方式执行,thread\u done
永远都不是真的
但除此之外,至少还有一个正确性问题:在没有同步的情况下,您正在读取和写入int-thread_-done[6]={0,0,0,0,0};
。这是未定义的行为,因此编译器可以执行它想要的操作
可能发生的情况是,编译器看到它可以缓存threadone\u private
的值,因为线程从未写入该值,因此该值不能更改(合法)。对std::cout
的外部调用意味着它不能确定该值在背后没有更改,因此它必须在每次新的迭代中读取该值(另外,std::cout在大多数实现中使用锁,这会导致同步,这又限制了编译器的假设).我对线程没有太多的经验,但是thread\u done
不是原子的,所以可能您正在经历一个竞争条件?我无法理解为什么这个调试行会对if条件函数是否如预期的那样是一个计时问题产生任何影响。该调试语句将需要时间来执行,改变所有事情的时间安排。谢谢你的评论,@Chipster。我认为这可能是一个竞争条件,特别是因为我以前在这段代码中犯过几次这个错误。但这次似乎不应该是这样,因为它100%使用4个线程或注释,但100%失败
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 = 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) {
//somewhere
std::mutex myMutex;
std::condition_variable myCondition;
int workersDone = 0;
/* main thread */
createWorkerThread1();
createWorkerThread2();
{
std::unique_lock<std::mutex> lock(myMutex); //waits until mutex is locked.
while(workersDone != 2) {
myCondition.wait(lock); //the mutex is unlocked while waiting
}
std::cout << "the data is ready now" << std::endl;
} //the lock is destroyed, unlocking the mutex
/* Worker thread */
while(true) {
{
std::unique_lock<std::mutex> lock(myMutex); //waits until mutex is locked
if(read_or_modify_a_piece_of_shared_data() == DATA_FINISHED) {
break; //lock leaves the scope, unlocks the mutex
}
}
prepare_everything_for_the_next_piece_of_shared_data(); //DO NOT access data here
}
//data is processed
++workersDone;
myCondition.notify_one(); //no mutex here. This wakes up the waiting thread