我在boost.asio项目中发现了一些奇怪的问题。 所以我做了一个样本控制台项目,同样的问题发生了。
以下是代码:
class server
{
public:
server()
: m_acceptor(m_ios)
{
m_work.reset(new boost::asio::io_service::work(m_ios));
m_thread = boost::thread(boost::bind(&boost::asio::io_service::run, &m_ios));
}
virtual ~server()
{
m_work.reset();
m_ios.stop();
m_thread.join();
}
void do_test()
{
m_ios.post(boost::bind(&server::handle_test, this));
}
private:
void handle_test()
{
m_value = 1234;
printf("server::handle_test() -> m_value %d.\n", m_value);
}
boost::shared_ptr<boost::asio::io_service::work> m_work;
boost::asio::io_service m_ios;
boost::thread m_thread;
boost::asio::ip::tcp::acceptor m_acceptor;
public:
int m_value;
};
void main()
{
server s;
s.do_test();
_getch(); // wait for a while
printf("main() -> m_value is %d.\n", s.m_value);
_getch();
}
行。所以用这个代码, 控制台输出将是:
server :: handle_test() - &gt; m_value是1234。
main() - &gt; m_value是1234。
按任意键继续。 。
右??
但奇怪的是,实际的控制台输出是:
server :: handle_test() - &gt; m_value是1234。
main() - &gt; m_value为0。
按任意键继续。 。
为什么???
有没有人可以解释这个?我如何从根本上解决它?
这是整个项目文件和exe。 https://www.dropbox.com/s/cflcmbuwgab1rxb/boost_asio_test.zip?dl=0
[测试环境]
Windows Embedded 8.1 Industry Pro x64
使用Visual Studio 2013编译(VisualStudioVersion 12.0.31101.0)
答案 0 :(得分:0)
您不能同步访问来自多个线程的共享数据。
这是数据竞赛。
数据竞赛是Undefined Behaviour。任何事情都可能发生。
通过同步对m_value
<强>更新强>
启用线程清理程序(gcc / clang上的-fsanitizer=thread
)时,您会收到 Live On Coliru
==================
WARNING: ThreadSanitizer: data race (pid=27230)
Read of size 4 at 0x7fff488eb360 by main thread:
#0 main /tmp/test.cpp:57 (test+0x0000004e2d82)
Previous write of size 4 at 0x7fff488eb360 by thread T1:
#0 server::handle_test() /tmp/test.cpp:36 (test+0x00000051259c)
#1 boost::_mfi::mf0<void, server>::operator()(server*) const /home/sehe/custom/boost/boost/bind/mem_fn_template.hpp:49 (test+0x00000051741e)
#2 void boost::_bi::list1<boost::_bi::value<server*> >::operator()<boost::_mfi::mf0<void, server>, boost::_bi::list0>(boost::_bi::type<void>, boost::_mfi::mf0<void, server>&, boost::_bi::list0&, int) /home/sehe/custom/boost/boost/bind/bind.hpp:255 (test+0x00000051705a)
#3 boost::_bi::bind_t<void, boost::_mfi::mf0<void, server>, boost::_bi::list1<boost::_bi::value<server*> > >::operator()() /home/sehe/custom/boost/boost/bind/bind.hpp:895 (test+0x000000516cbf)
#4 void boost::asio::asio_handler_invoke<boost::_bi::bind_t<void, boost::_mfi::mf0<void, server>, boost::_bi::list1<boost::_bi::value<server*> > > >(boost::_bi::bind_t<void, boost::_mfi::mf0<void, server>, boost::_bi::list1<boost::_bi::value<server*> > >&, ...) /home/sehe/custom/boost/boost/asio/handler_invoke_hook.hpp:69 (test+0x000000516a35)
#5 void boost_asio_handler_invoke_helpers::invoke<boost::_bi::bind_t<void, boost::_mfi::mf0<void, server>, boost::_bi::list1<boost::_bi::value<server*> > >, boost::_bi::bind_t<void, boost::_mfi::mf0<void, server>, boost::_bi::list1<boost::_bi::value<server*> > > >(boost::_bi::bind_t<void, boost::_mfi::mf0<void, server>, boost::_bi::list1<boost::_bi::value<server*> > >&, boost::_bi::bind_t<void, boost::_mfi::mf0<void, server>, boost::_bi::list1<boost::_bi::value<server*> > >&) /home/sehe/custom/boost/boost/asio/detail/handler_invoke_helpers.hpp:37 (test+0x0000005167e0)
#6 boost::asio::detail::completion_handler<boost::_bi::bind_t<void, boost::_mfi::mf0<void, server>, boost::_bi::list1<boost::_bi::value<server*> > > >::do_complete(boost::asio::detail::task_io_service*, boost::asio::detail::task_io_service_operation*, boost::system::error_code const&, unsigned long) /home/sehe/custom/boost/boost/asio/detail/completion_handler.hpp:68 (test+0x0000005162b7)
#7 boost::asio::detail::task_io_service_operation::complete(boost::asio::detail::task_io_service&, boost::system::error_code const&, unsigned long) /home/sehe/custom/boost/boost/asio/detail/task_io_service_operation.hpp:38 (test+0x000000532a63)
#8 boost::asio::detail::task_io_service::do_run_one(boost::asio::detail::scoped_lock<boost::asio::detail::posix_mutex>&, boost::asio::detail::task_io_service_thread_info&, boost::system::error_code const&) /home/sehe/custom/boost/boost/asio/detail/impl/task_io_service.ipp:372 (test+0x00000052db18)
#9 boost::asio::detail::task_io_service::run(boost::system::error_code&) /home/sehe/custom/boost/boost/asio/detail/impl/task_io_service.ipp:149 (test+0x00000052721a)
#10 boost::asio::io_service::run() /home/sehe/custom/boost/boost/asio/impl/io_service.ipp:59 (test+0x0000005266ce)
#11 server::worker() /tmp/test.cpp:17 (test+0x000000518f19)
#12 boost::_mfi::mf0<void, server>::operator()(server*) const /home/sehe/custom/boost/boost/bind/mem_fn_template.hpp:49 (test+0x00000051741e)
#13 void boost::_bi::list1<boost::_bi::value<server*> >::operator()<boost::_mfi::mf0<void, server>, boost::_bi::list0>(boost::_bi::type<void>, boost::_mfi::mf0<void, server>&, boost::_bi::list0&, int) /home/sehe/custom/boost/boost/bind/bind.hpp:255 (test+0x00000051705a)
#14 boost::_bi::bind_t<void, boost::_mfi::mf0<void, server>, boost::_bi::list1<boost::_bi::value<server*> > >::operator()() /home/sehe/custom/boost/boost/bind/bind.hpp:895 (test+0x000000516cbf)
#15 boost::detail::thread_data<boost::_bi::bind_t<void, boost::_mfi::mf0<void, server>, boost::_bi::list1<boost::_bi::value<server*> > > >::run() /home/sehe/custom/boost/boost/thread/detail/thread.hpp:116 (test+0x00000051d5a9)
#16 thread_proxy thread.cpp (libboost_thread.so.1.59.0+0x000000011aa9)
As if synchronized via sleep:
#0 nanosleep <null> (test+0x000000475c10)
#1 boost::this_thread::hiden::sleep_for(timespec const&) <null> (libboost_thread.so.1.59.0+0x000000012885)
#2 void boost::this_thread::sleep_for<long, boost::ratio<1l, 1000l> >(boost::chrono::duration<long, boost::ratio<1l, 1000l> > const&) /home/sehe/custom/boost/boost/thread/v2/thread.hpp:112 (test+0x0000004e65fb)
#3 main /tmp/test.cpp:56 (test+0x0000004e2b71)
Location is stack of main thread.
Thread T1 (tid=27234, running) created by main thread at:
#0 pthread_create <null> (test+0x00000047aaf1)
#1 boost::thread::start_thread_noexcept() <null> (libboost_thread.so.1.59.0+0x000000010ea9)
#2 thread<boost::_bi::bind_t<void, boost::_mfi::mf0<void, server>, boost::_bi::list1<boost::_bi::value<server *> > > > /home/sehe/custom/boost/boost/thread/detail/thread.hpp:266 (test+0x000000519122)
#3 server /tmp/test.cpp:13 (test+0x0000004e58b3)
#4 main /tmp/test.cpp:53 (test+0x0000004e2855)
SUMMARY: ThreadSanitizer: data race /tmp/test.cpp:57 main
==================
server::handle_test() -> m_value 1234
main() -> m_value is 1234
ThreadSanitizer: reported 1 warnings