Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/sorting/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 在c+中工作不正常的情况下在内部工作+;_C++_Multithreading_While Loop - Fatal编程技术网

C++ 在c+中工作不正常的情况下在内部工作+;

C++ 在c+中工作不正常的情况下在内部工作+;,c++,multithreading,while-loop,C++,Multithreading,While Loop,我在C有一个奇怪的情况(至少对我来说是D)++ 我的代码是: static void startThread(Object* r){ while(true) { while(!r->commands->empty()) { doSomthing(); } } } 我使用boost作为线程启动这个函数,其中r中的命令是队列。。。我在另一个线程中填充此队列 问题是,如果我先填满队列,然后开始

我在C有一个奇怪的情况(至少对我来说是D)++

我的代码是:

static void startThread(Object* r){
    while(true)
    {
        while(!r->commands->empty())
        {
            doSomthing();
        }
    }
}
我使用boost作为线程启动这个函数,其中r中的命令是队列。。。我在另一个线程中填充此队列

问题是,如果我先填满队列,然后开始这一步,一切都会很好。。。但是如果我先运行startThread,然后填充队列命令,它就不工作了。。。doSomething()将不会运行

但是,如果我修改startThread:

static void startThread(Object* r){
    while(true)
    {
        std::cout << "c" << std::endl;
        while(!r->commands->empty())
        {
            doSomthing();
        }
    }
}
静态void startThread(Object*r){
while(true)
{
std::cout empty())
{
dosomshing();
}
}
}
我只是加了一句。。。它正在工作。。。有人能解释为什么它是与cout一起工作而不是与cout一起工作吗?或者有人知道会出什么问题

也许编译器正在进行某种优化?我不这么认为…:( 谢谢

但是如果我先运行startThread,然后再填充队列命令,它就不工作了…doSomething()将不会运行

当然不是!你期望什么?你的队列是空的,所以
!r->commands->empty()
将是
false

我刚刚加了cout…它正在工作

您很幸运。
cout
相对较慢,因此您的主线程有机会在第一次执行内部
测试之前填充队列

那么为什么在主线程填充了
r->commands
之后,线程看不到更新版本的命令呢?因为代码中没有任何内容表明变量将从外部更改,所以编译器假定它不会更改


<>实际上,编译器看到你的代码> R< /C>的“强>不能< /强>更改,因此它可以从内部循环中删除冗余检查。当使用多线程代码时,你需要明确地告诉C++变量可以从不同的上下文中改变,使用.< /P>< P>当你先运行线程然后填充T时。不进入内部循环的队列是合乎逻辑的,因为
test!r->commands->empty()
为true。在添加
cout
语句后,它开始工作,因为打印输出需要一些时间,同时另一个线程填满了队列。因此该条件再次变为true。但在多线程环境中,依赖这一事实进行编程并不好。

有两个相互关联的问题:

  • 您没有强制重新加载
    r->commands
    r->commands-Yempty()
    ,因此,您的编译器在努力寻找性能顶峰的同时,缓存了结果。如果无法证明缓存仍然有效,则添加更多代码可能会使编译器删除此优化
  • 您有一个数据竞争,因此您的程序有未定义的行为。(我假设
    doSomething()
    删除一个元素,其他一些线程添加元素。

    1.10多线程执行和数据争用§21 如果程序在不同线程中包含两个冲突的操作,则程序的执行包含数据竞争, 其中至少有一个不是原子的,而且两个都不是在另一个之前发生的 未定义的行为。[注意:可以显示正确使用互斥量和内存顺序的程序_- seq_cst防止所有数据争用且不使用其他同步操作的操作的行为与 由其组成线程执行的操作被简单地交错,每个值的计算 对象从该交织中对该对象的最后一个副作用中提取。这通常称为 “顺序一致性”。然而,这仅适用于无数据竞争程序和无数据竞争程序 无法观察大多数不改变单线程程序语义的程序转换。在 事实上,大多数单线程程序转换仍然被允许,因为 因此,必须执行未定义的操作。-结束注释] 二十二


如果只发送空队列,线程将很快结束。当您进行打印时,父线程将有机会填充队列。请使用一些同步。如果队列不是线程安全的,则从2个线程更新队列可能会导致未定义的结果。它正在“工作”使用cout是因为您有一个bug,它导致的减速是掩蔽。首先,您需要使用某种同步机制来保护对队列的访问。@Dusan Plavak-
,但是如果我先运行startThread
,这就是问题所在。您认为当您调用启动线程的函数时,线程函数立即执行。这是一个错误的假设。如果不使用(甚至不学习)编写多线程程序,您将无法逃脱惩罚关于正确的同步,例如信号量、互斥体、原子操作等@PaulMcKenzie我没有假设哪个线程先启动,我确保startThread先启动…不管怎样,问题就像Konrad Rudolph在提供链接时描述的那样…@DusanPlavak-您如何确保startThread函数先启动st?您的问题中不清楚该函数是如何启动的。您是否直接调用startThread函数?
startThread();FillUpTheQueue();
您是这样做的?还是这样做的:
callThreadedFunction(startThread);FillUpTheQueue()
callThreadedFunction
是一些启动线程的通用函数(不管它是不是boost).我不认为是这样,因为对象r是指针,所以如果我以后感觉到命令是否为空,这并不重要…?外部
轮询
r->commands
列表。但是编译器没有识别,对象是从“外部”更改的。您必须使用volatile命令告诉编译器。@KonradRudolph W