【问题标题】:boost asio semaphore-like solutionboost asio 类似信号量的解决方案
【发布时间】:2011-10-17 12:43:24
【问题描述】:

此问题是this 问题的后续问题。无论如何,这就是动机 - 来自原始问题评论的一点 c/p:

我希望能够在多个线程上发布一组作业(CalcFib 函数),然后当作业结束时,另一组作业(CalcFib2 函数),也在多个线程上。这个循环循环了很多次(这里是两个),所以我认为最好的办法是创建boost::asio::io_service并在循环开始时创建线程,这样我就不必每次循环都创建&销毁线程开始/结束。

我创建了两个 int 变量,错误地命名为 semaphore_**,并在上述函数中递减它们。等待作业组完成的代码是简单的while,如下所示。至少在我看来,该解决方案有效。

使用while 等待真的可行吗?我错过了什么?有没有更好的方法来做到这一点?

我的代码如下所示:

#include <boost/asio.hpp>
#include <boost/shared_ptr.hpp>
#include <boost/thread.hpp>
#include <boost/thread/mutex.hpp>
#include <boost/bind.hpp>
#include <iostream>

boost::mutex global_stream_lock;
int semaphore_fib = 0;
int semaphore_fib2 = 0;

void WorkerThread( boost::shared_ptr< boost::asio::io_service > io_service)
{
    global_stream_lock.lock();
    std::cout << "[" << boost::this_thread::get_id()
        << "] Thread Start" << std::endl;
    global_stream_lock.unlock();

    io_service->run();

    global_stream_lock.lock();
    std::cout << "[" << boost::this_thread::get_id()
        << "] Thread Finish" << std::endl;
    global_stream_lock.unlock();
}

size_t fib( size_t n )
{
    if ( n <= 1 )
    {
        return n;
    }
    boost::this_thread::sleep( boost::posix_time::milliseconds( 1000 ) );
    return fib( n - 1 ) + fib( n - 2);
}

void CalcFib( size_t n )
{
    global_stream_lock.lock();
    std::cout << "[" << boost::this_thread::get_id()
        << "] Now calculating fib( " << n << " ) " << std::endl;
    global_stream_lock.unlock();

    size_t f = fib( n );

    global_stream_lock.lock();
    std::cout << "[" << boost::this_thread::get_id()
        << "] fib( " << n << " ) = " << f << std::endl;
    semaphore_fib = semaphore_fib-1;
    global_stream_lock.unlock();
}

void CalcFib2( size_t n )
{
    global_stream_lock.lock();
    std::cout << "\t\t[" << boost::this_thread::get_id()
        << "] Now calculating fib2( " << n << " ) " << std::endl;
    global_stream_lock.unlock();

    size_t f = fib( n );

    global_stream_lock.lock();
    std::cout << "\t\t[" << boost::this_thread::get_id()
        << "] fib2( " << n << " ) = " << f << std::endl;
    semaphore_fib2=semaphore_fib2-1;
    global_stream_lock.unlock();
}

int main( int argc, char * argv[] )
{
    boost::shared_ptr< boost::asio::io_service > io_service(
        new boost::asio::io_service
        );
    boost::shared_ptr< boost::asio::io_service::work > work(
        new boost::asio::io_service::work( *io_service )
        );
    boost::asio::io_service::strand strand( *io_service );

    global_stream_lock.lock();
    std::cout << "[" << boost::this_thread::get_id()
        << "] The program will exit when all work has finished."
        << std::endl;
    global_stream_lock.unlock();

    boost::thread_group worker_threads;
    for( int x = 0; x < 2; ++x )
    {
        worker_threads.create_thread( 
            boost::bind( &WorkerThread, io_service)
            );
    }
    for(int loop_no=0; loop_no<2; ++loop_no)
    {
        semaphore_fib=3;
        io_service->post( boost::bind( CalcFib, 5 ) );
        io_service->post( boost::bind( CalcFib, 4 ) );
        io_service->post( boost::bind( CalcFib, 3 ) );
        while(semaphore_fib>0)
        {
            // waiting
        }

        global_stream_lock.lock();
        std::cout << "[" << boost::this_thread::get_id()
            << "] ******* CalcFib group finished ********" << std::endl;
        global_stream_lock.unlock();

        semaphore_fib2=3;
        io_service->post( boost::bind( CalcFib2, 2 ) );
        io_service->post( boost::bind( CalcFib2, 1 ) );
        io_service->post( boost::bind( CalcFib2, 1 ) );
        while(semaphore_fib2>0)
        {
            // waiting
        }
        global_stream_lock.lock();
        std::cout << "[" << boost::this_thread::get_id()
            << "] ******* CalcFib2 group finished  ********" << std::endl;
        global_stream_lock.unlock();
    }
    work.reset();
    worker_threads.join_all();

    return 0;
} 

【问题讨论】:

    标签: c++ multithreading boost boost-asio boost-thread


    【解决方案1】:

    这就是我在main() 中的while 循环中解决太多if 语句的方法。

    • 添加了boost::condition_variable cv;boost::mutex mx; 作为全局变量
    • 已添加boost::lock_guard&lt;boost::mutex&gt; lk(mx);cv.notify_all();CalcFibCalcFib2 函数的末尾
    • 已添加boost::unique_lock&lt;boost::mutex&gt; lk(mx); cv.wait(lk); 在每个while 循环中

    这样我就实现了while循环中的if语句只有在cv.notify_all()执行时才会执行。

    【讨论】:

      猜你喜欢
      • 2014-01-03
      • 1970-01-01
      • 1970-01-01
      • 2017-12-25
      • 1970-01-01
      • 2020-11-17
      • 1970-01-01
      • 1970-01-01
      • 2021-05-01
      相关资源
      最近更新 更多