首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >将作业发送到std::线程

将作业发送到std::线程
EN

Stack Overflow用户
提问于 2016-02-29 22:00:51
回答 1查看 68关注 0票数 0

我对std::线程非常陌生,我很快就意识到创建这些线程非常昂贵,至少在我运行W7的计算机上是这样的。因此,我决定创建我的线程并使用以下示例代码将作业发送给它:variable

我的代码运行良好,没有崩溃,但是我没有注意到性能的提高,所以我测量了作业完成的时间和主线程检测作业的时间之间的差异(请参阅WaitUntilJobFinished() ),我注意到在一些罕见的情况下,时差超过2毫秒。

有人发现密码有什么问题吗?

代码:

代码语言:javascript
复制
class CJobParameters
{
public:
};

typedef void (*CJobFunc)( const CJobParameters * );

class CThread
{   
public:
    void Start();
    void WaitUntilJobDone();
    void StartJob( CJobFunc inJobFunc, const CJobParameters * inJobParameters );

    std::thread m_stdThread;

    CJobFunc                m_jobFunc       = nullptr;
    const CJobParameters *  m_jobParameters = nullptr;
    //std::atomic<bool>     m_jobDone       = true;
    std::mutex              m_mutex;
    std::condition_variable m_cv;

    __int64 m_jobDoneAt = 0;
    __int64 m_threadJoinedAt = 0;
    __int64 m_lostTime = 0;
};

class CThreads
{
public:
    static void Start();
    static CThread  threadArray[ JOB_COUNT ];
};


void ThreadMain( CThread * inThread )
{
    while ( true )
    {
        std::unique_lock<std::mutex> lk( inThread->m_mutex );
        inThread->m_cv.wait(lk, [ inThread ]{return inThread->m_jobParameters != nullptr;});
        if ( inThread->m_jobFunc )
        {
            (*inThread->m_jobFunc)( inThread->m_jobParameters );
            inThread->m_jobFunc = nullptr;
            inThread->m_jobParameters = nullptr;
            inThread->m_jobDoneAt = COSToolbox::QuerySystemTime2();
        }
        lk.unlock();
        inThread->m_cv.notify_one();
        std::this_thread::sleep_for( std::chrono::nanoseconds(0) );
    }
}

void CThread::StartJob( CJobFunc inJobFunc, const CJobParameters * inJobParameters )
{
    std::lock_guard<std::mutex> lk( m_mutex );
    m_jobFunc           = inJobFunc;
    m_jobParameters     = inJobParameters;
    m_cv.notify_one();
}

void CThread::Start()
{
    m_stdThread = std::thread( ThreadMain, this );
}

void CThread::WaitUntilJobDone()
{
    std::unique_lock<std::mutex> lk( m_mutex );
    m_cv.wait(lk, [ this ]{return this->m_jobParameters == nullptr;});

    m_threadJoinedAt = COSToolbox::QuerySystemTime2();
    m_lostTime = m_threadJoinedAt - m_jobDoneAt;
    LOG_INFO( "Thread joined with %f ms lost", (Float32)m_lostTime / 1000 );
}


CThread CThreads::threadArray[ JOB_COUNT ];
void CThreads::Start()
{
    for ( Int32 i = 0; i < JOB_COUNT; ++i )
    {
        threadArray[i].Start();
    }
}

void MyJobFunc( const CJobParameters  * jobParameters )
{
    // do job here
}
void main()
{
    CThreads::Start();
    while(true)
    {
        CJobParameters jobParametersArray[ JOB_COUNT ];
        for ( Int32 i = 0; i < JOB_COUNT; ++i )
        {
            CThread & thread = CThreads::threadArray[ i ];
            CJobParameters& jobParameters = jobParametersArray[ i ];
            jobParameters.m_ // Fill in params
            thread.StartJob( &MyJobFunc, &jobParameters );
        }
        for ( Int32 i = 0; i < JOB_COUNT; ++i )
        {
            CThread & thread = CThreads::threadArray[ i ];
            // Prints 2 ms sometimes whith i = 0
            thread.WaitUntilJobDone();
        }
     }
}
EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2016-02-29 22:34:21

有两件事:

您将无条件地生成处理器时间,并且在一些旧版本的windows上,您将生成整个进程,而不仅仅是线程:

代码语言:javascript
复制
std::this_thread::sleep_for( std::chrono::nanoseconds(0) );

这个产量是不必要的。我怀疑你这么做的原因是,如果没有它,你会得到一个自旋循环,这是因为你同时在读和写一个条件变量。

您需要两个条件变量,一个用于待定工作,一个用于已完成的工作。通常,侦听器将条件变量或包含它的结构作为参数传递给线程函数,从而允许您从dispatcher传递一个条件变量。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/35710560

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档