Warning: file_get_contents(/data/phpspider/zhask/data//catemap/7/arduino/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++_Multithreading_Boost_Boost Thread - Fatal编程技术网

C++ 增加计数器时避免争用条件

C++ 增加计数器时避免争用条件,c++,multithreading,boost,boost-thread,C++,Multithreading,Boost,Boost Thread,我以前也在这个话题上发表过文章,但到目前为止我还没有多少运气。我把它归结为我的一个坏问题。这一次,我制作了一个简短的可编译示例,显示了我试图避免的不良行为。我希望大家对此表示感谢 问题是两个(或更多)线程被设置为运行同一进程,并且它们的“id”决定了它们对变量数据的哪一部分进行操作。当前,两个线程都将更新计数器 电流输出如下所示 tid = 0, var[tid] = 0 tid = 0, var[tid] = 1 tid = 0, var[tid] = 2 tid = 0, var[tid]

我以前也在这个话题上发表过文章,但到目前为止我还没有多少运气。我把它归结为我的一个坏问题。这一次,我制作了一个简短的可编译示例,显示了我试图避免的不良行为。我希望大家对此表示感谢

问题是两个(或更多)线程被设置为运行同一进程,并且它们的“id”决定了它们对变量数据的哪一部分进行操作。当前,两个线程都将更新计数器

电流输出如下所示

tid = 0, var[tid] = 0
tid = 0, var[tid] = 1
tid = 0, var[tid] = 2
tid = 0, var[tid] = 3
tid = 0, var[tid] = 4
tid = 0, var[tid] = 5
tid = 0, var[tid] = 6
tid = 0, var[tid] = 7
tid = 0, var[tid] = 8
tid = 0, var[tid] = 9
tid = 1, var[tid] = 0
Press any key to continue . . .
期望的输出应该是这样的

tid = 0, var[tid] = 0
tid = 1, var[tid] = 0
tid = 0, var[tid] = 1
tid = 1, var[tid] = 1
tid = 0, var[tid] = 2
tid = 1, var[tid] = 2
tid = 0, var[tid] = 3
tid = 1, var[tid] = 3 etc.
如蒙指导,不胜感激

编辑:我用预期的代码更新了答案

[注意这里效率很重要,我希望尽快完成流程]

#include <iostream>  
#include <boost/thread.hpp>

int var[2];
int mT;
int mTotalSamples;
boost::mutex mCountMutex;
boost::thread *threadMap[2];

using namespace std;

void process()
{
    int tid = 1;

    // sleep for 1 seconds - just to make sure threadMap 
    // has been assigned (only ncessary for this demo).
    boost::this_thread::sleep(boost::posix_time::seconds(1));

    if (threadMap[0]->get_id() == boost::this_thread::get_id()){ tid = 0;}

    while ( mT < mTotalSamples ) 
    {
        // perform processing
        var[tid] = mT; 
        // processing complete

        mCountMutex.lock(); // (a thread waits to aquire mutex)
        cout << "tid = " << tid << ", var[tid] = " << var[tid] << endl;
        mT++;           // How to stop both threads incrementing this?      
        mCountMutex.unlock();       
    }   
}

int main()
{
    boost::thread_group threads;

    mT = 0;
    mTotalSamples = 10;

    threadMap[0] = threads.create_thread( boost::bind(&process) );
    threadMap[1] = threads.create_thread( boost::bind(&process) );

    threads.join_all();

    return 0;
}
#包括
#包括
int-var[2];
int mT;
int mTotalSamples;
mutex-mCountMutex;
boost::thread*threadMap[2];
使用名称空间std;
无效过程()
{
int-tid=1;
//睡眠1秒钟-只是为了确保threadMap
//已分配(仅此演示不需要)。
boost::this_线程::sleep(boost::posix_时间::秒(1));
if(threadMap[0]->get_id()==boost::this_thread::get_id()){tid=0;}
而(mT<总样本数)
{
//执行处理
var[tid]=mT;
//处理完成
mCountMutex.lock();/(线程等待获取互斥)

cout从您的预期输出判断,您希望您的线程在每次更新后进行同步。
boost
库提供了这样的功能,如果您在
进程的while循环开始或结束时为它设置了一个
wait
,应该可以实现这一功能

#include <iostream>  
#include <boost/thread.hpp>

int var[2];
int mT;
int mTotalSamples;
boost::mutex mCountMutex;
boost::thread *threadMap[2];
boost::barrier bar(2);

using namespace std;

void process()
{
    int tid = 1;        

    // sleep for 2 seconds - just to make sure threadMap 
    // has been assigned (only ncessary for this demo).
    boost::this_thread::sleep(boost::posix_time::seconds(2));

    if (threadMap[0]->get_id() == boost::this_thread::get_id()){ tid = 0;}

    while ( mT < mTotalSamples ) 
    {
        // perform processing
        var[tid] = mT; 
        // processing complete


        bar.wait();
        if (threadMap[0]->get_id() == boost::this_thread::get_id())
        {
            mT++;               
            cout << "var[0] = " << var[0] << endl;
            cout << "var[1] = " << var[1] << endl;                      
        }           
        bar.wait();
    }   
}

int main()
{
    boost::thread_group threads;

    mT = 0;
    mTotalSamples = 10;

    threadMap[0] = threads.create_thread( boost::bind(&process) );
    threadMap[1] = threads.create_thread( boost::bind(&process) );

    threads.join_all();

    return 0;
}
#包括
#包括
int-var[2];
int mT;
int mTotalSamples;
mutex-mCountMutex;
boost::thread*threadMap[2];
增压:隔离栅(2);
使用名称空间std;
无效过程()
{
int-tid=1;
//睡眠2秒钟-只是为了确保threadMap
//已分配(仅此演示不需要)。
boost::this_线程::sleep(boost::posix_时间::秒(2));
if(threadMap[0]->get_id()==boost::this_thread::get_id()){tid=0;}
而(mT<总样本数)
{
//执行处理
var[tid]=mT;
//处理完成
等等();
if(线程映射[0]->get_id()==boost::this_thread::get_id())
{
mT++;

不能将此
int mT;
local-in-process()设置为全局。 或者您需要一个
int mT[2];

那么您就不需要互斥锁了。

听起来您希望线程能够交错访问互斥锁。但是,您的代码中没有强制执行互斥锁的内容。如果您希望操作以特定的顺序开始,那么线程可能不是解决方案…@OliCharlesworth互斥锁不是问题,每个线程应该只执行p当计数器增加一次时,执行行,var[tid]=mT;。但是,老实说,我认为使用cout可能会混淆问题。仅为了保护计数器,可以使用联锁操作,如
LONG\u cdecl InterlockedIncrement(LONG volatile*加数);
在windows上。您真的需要保护您的
var
变量吗?尝试调度两个线程以相互协作没有多大意义,您也可以忘记线程,只需按程序/手动调度操作。线程在切换到另一个线程之前会有一定的执行时间在那个时候,线程可以完成比你想要的更多的工作,并且迫使一个线程向另一个线程让步可能会影响调度器的效率,从而影响应用程序的整体性能。你应该真正考虑线程是否是为你的目的所必需的。it@dreamlax感谢s、 我知道这个例子有点做作,因为我已经应用了简化,使问题易于理解。事实上,一个线程的一个循环可能需要几秒钟,在实践中,我会执行尽可能多的线程作为核心,并划分“var”的更新在这些线程之间平均分配,从而减少完成一个循环的时间。线程绝对适用于此目的。感谢您的评论,尽管添加第二个计数器无助于满足我的需要。同样,这只是因为我将我的问题简化为一个更简单的问题,为了使问题更具可读性,上下文会丢失一些什么t、 @AlexS:好的,我已经批准了你的编辑,谢谢!顺便说一句,在你的应用程序中,有必要对
bar.wait()
进行两次调用吗?我原以为在循环的顶部只调用一次就足够了。嗯,我想是的,但我可能错了。如果没有它,我认为线程2有可能完成,var[tid]=mT;在线程1管理递增mT之前。第二个屏障确保这绝对不会发生。@Alex:你能验证一下吗?诸如屏障之类的同步点会显著降低并行性能,因此你应该尽量少用它们!我认为有必要确定两个,但只有当t处理量增加到实际大小。即,如果var[0]表示500万次操作,而var[1]表示2000万个操作,那么线程1将在线程2完成其工作之前增加计数器。@Alex:好的,但是如果在循环的底部(即计数器增加之后)设置屏障就足够了吗?