C++ strand在boost asio中的优势是什么?

C++ strand在boost asio中的优势是什么?,c++,boost,boost-asio,C++,Boost,Boost Asio,据我所知,正在学习boost asio并找到一个名为“strand”的课程。 如果只有一个io_服务与特定链相关联,则按链发布句柄 示例(来自) boost::shared_ptrio_service( 新的boost::asio::io\u服务 ); boost::shared_ptrwork( 新的boost::asio::io_服务::工作(*io_服务) ); boost::asio::io_服务::串(*io_服务); boost::线程组工作线程; 对于(int x=0;x

据我所知,正在学习boost asio并找到一个名为“strand”的课程。 如果只有一个io_服务与特定链相关联,则按链发布句柄

示例(来自)

boost::shared_ptrio_service(
新的boost::asio::io\u服务
);
boost::shared_ptrwork(
新的boost::asio::io_服务::工作(*io_服务)
);
boost::asio::io_服务::串(*io_服务);
boost::线程组工作线程;
对于(int x=0;x<2;++x)
{
创建线程(boost::bind(&WorkerThread,io_服务));
}
boost::this_线程::sleep(boost::posix_时间::毫秒(1000));
post(boost::bind(&PrintNum,1));
post(boost::bind(&PrintNum,2));
post(boost::bind(&PrintNum,3));
post(boost::bind(&PrintNum,4));
post(boost::bind(&PrintNum,5));

然后串将为我们序列化处理程序执行。但是这样做的好处是什么?如果我们希望任务序列化,为什么不创建一个线程(例如:在for循环中使x=1)?

想想一个系统,其中一个
io_服务
管理数百个网络连接的套接字。为了能够并行化工作负载,系统维护了一个工作线程池,这些工作线程调用
io\u service::run

现在,这样一个系统中的大多数操作都可以并行运行。但有些必须序列化。例如,您可能不希望在同一套接字上同时执行多个写操作。然后,您将使用每个套接字一个串来同步写入:对不同套接字的写入仍然可以同时发生,而对相同套接字的写入将被序列化。工作线程不必关心同步或不同的套接字,它们只需要抓取
io\u service::run
交给它们的任何东西


有人可能会问:为什么我们不能用互斥来代替同步呢?strand的优点是,如果strand已经在工作,那么工作线程首先就不会得到调度。使用互斥锁时,工作线程将获得回调,然后阻止锁定尝试,在互斥锁可用之前阻止线程执行任何有用的工作。

我知道它太旧了,但希望它能通过示例帮助新用户理解。阅读代码中的注释

#define BOOST_DATE_TIME_NO_LIB
#define BOOST_REGEX_NO_LIB

#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;

void WorkerThread(boost::shared_ptr<boost::asio::io_service> iosvc, int counter) {
    global_stream_lock.lock();
    std::cout << "Thread " << std::this_thread::get_id() << ", " << counter << " Start.\n";
    global_stream_lock.unlock();

    iosvc->run();

    global_stream_lock.lock();
    std::cout << "Thread " << counter << " End.\n";
    global_stream_lock.unlock();
}

void async_send_handler(int number) {
    std::cout << "Number: " << number << ", threadID: " << std::this_thread::get_id() << std::endl;
}

int main(void) {
    boost::shared_ptr<boost::asio::io_service> io_svc(
        new boost::asio::io_service
    );

    boost::shared_ptr<boost::asio::io_service::work> worker(
        new boost::asio::io_service::work(*io_svc)
    );

    boost::asio::io_service::strand strand(*io_svc);

    global_stream_lock.lock();
    std::cout << "The program will exit once all work has finished.\n";
    global_stream_lock.unlock();

    boost::thread_group threads;
    for( int i = 1; i <= 5; i++ )
        threads.create_thread(boost::bind(&WorkerThread, io_svc, i));

    boost::this_thread::sleep(boost::posix_time::milliseconds(500));

    // Imagine you are invoking async_send on tcp or udp socket several times
    // and you want the handlers of this async_send call to be invoked sequentially

    // This code is almost equal to calling handlers of socket.async_send.
    // The handlers are invoked concurently and the order might be arbitrary
    io_svc->post(boost::bind(&async_send_handler, 1));
    io_svc->post(boost::bind(&async_send_handler, 2));
    io_svc->post(boost::bind(&async_send_handler, 3));
    io_svc->post(boost::bind(&async_send_handler, 4));
    io_svc->post(boost::bind(&async_send_handler, 5));

    // This code will do what you exactly want;
    // It will execute the handlers sequentially in that order
    strand.post(boost::bind(&async_send_handler, 1));
    strand.post(boost::bind(&async_send_handler, 2));
    strand.post(boost::bind(&async_send_handler, 3));
    strand.post(boost::bind(&async_send_handler, 4));
    strand.post(boost::bind(&async_send_handler, 5));

    worker.reset();

    threads.join_all();

    return 0;
}
#定义BOOST_DATE_TIME_NO_LIB
#定义BOOST_REGEX_NO_LIB
#包括
#包括
#包括
#包括
#包括
#包括
互斥全局流锁;
void WorkerThread(boost::shared_ptr iosvc,int counter){
全局_流_lock.lock();

std::我知道这个问题很老了,但我想提一提一篇博客文章,它剖析了一个关于股的观点()。免责声明:我是作者。
#define BOOST_DATE_TIME_NO_LIB
#define BOOST_REGEX_NO_LIB

#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;

void WorkerThread(boost::shared_ptr<boost::asio::io_service> iosvc, int counter) {
    global_stream_lock.lock();
    std::cout << "Thread " << std::this_thread::get_id() << ", " << counter << " Start.\n";
    global_stream_lock.unlock();

    iosvc->run();

    global_stream_lock.lock();
    std::cout << "Thread " << counter << " End.\n";
    global_stream_lock.unlock();
}

void async_send_handler(int number) {
    std::cout << "Number: " << number << ", threadID: " << std::this_thread::get_id() << std::endl;
}

int main(void) {
    boost::shared_ptr<boost::asio::io_service> io_svc(
        new boost::asio::io_service
    );

    boost::shared_ptr<boost::asio::io_service::work> worker(
        new boost::asio::io_service::work(*io_svc)
    );

    boost::asio::io_service::strand strand(*io_svc);

    global_stream_lock.lock();
    std::cout << "The program will exit once all work has finished.\n";
    global_stream_lock.unlock();

    boost::thread_group threads;
    for( int i = 1; i <= 5; i++ )
        threads.create_thread(boost::bind(&WorkerThread, io_svc, i));

    boost::this_thread::sleep(boost::posix_time::milliseconds(500));

    // Imagine you are invoking async_send on tcp or udp socket several times
    // and you want the handlers of this async_send call to be invoked sequentially

    // This code is almost equal to calling handlers of socket.async_send.
    // The handlers are invoked concurently and the order might be arbitrary
    io_svc->post(boost::bind(&async_send_handler, 1));
    io_svc->post(boost::bind(&async_send_handler, 2));
    io_svc->post(boost::bind(&async_send_handler, 3));
    io_svc->post(boost::bind(&async_send_handler, 4));
    io_svc->post(boost::bind(&async_send_handler, 5));

    // This code will do what you exactly want;
    // It will execute the handlers sequentially in that order
    strand.post(boost::bind(&async_send_handler, 1));
    strand.post(boost::bind(&async_send_handler, 2));
    strand.post(boost::bind(&async_send_handler, 3));
    strand.post(boost::bind(&async_send_handler, 4));
    strand.post(boost::bind(&async_send_handler, 5));

    worker.reset();

    threads.join_all();

    return 0;
}