线程在编译或运行时确定?

我只问自己:当我在代码中创建线程池时
然后我编译代码,
编译后的代码是否有每个线程的副本?

如果我使用宏函数,并将其传递给线程,
在编译期间“我在想什么”或在运行时期间扩展了这个宏,
如果它在编译时为什么下面的代码需要互斥体:

#include <boost/asio.hpp>
#include <boost/thread.hpp>
#include <boost/date_time.hpp>
#include <iostream>
namespace asio = boost::asio;
#define PRINT_ARGS(msg) do {
boost::lock_guard<boost::mutex> lg(mtx); 
std::cout << '[' << boost::this_thread::get_id() 
<< "] " << msg << std::endl; 
} while (0)
int main() {
asio::io_service service;
boost::mutex mtx;

for (int i = 0; i < 20; ++i) {
service.post([i, &mtx]() {
PRINT_ARGS("Handler[" << i << "]");
boost::this_thread::sleep(
boost::posix_time::seconds(1));
});
}

boost::thread_group pool;
for (int i = 0; i < 4; ++i) {
pool.create_thread([&service]() { service.run(); });
}
pool.join_all();
}

这里lock_guard使cout成为关键部分,尽管只有主线程才会被发布到io_service
那么运行任务的线程将在已经创建好的lamda函数队列中工作>>>>这使我认为不需要互斥锁?
这种想法是对的吗?

这里我将模拟编译过程中的宏扩展:

#include <boost/asio.hpp>
#include <boost/thread.hpp>
#include <boost/date_time.hpp>
#include <iostream>
namespace asio = boost::asio;


#define PRINT_ARGS(msg) do {
boost::lock_guard<boost::mutex> lg(mtx); 
std::cout << '[' << boost::this_thread::get_id() 
<< "] " << msg << std::endl; 
} while (0)

int main() {
asio::io_service service;
boost::mutex mtx;

for (int i = 0; i < 20; ++i) {
service.post([i, &mtx]() {

//PRINT_ARGS("Handler[" << i << "]");//>>>>>this will be

do {
boost::lock_guard<boost::mutex> lg(mtx); 
std::cout << '[' << boost::this_thread::get_id() 
<< "] " << "Handler[" << i << "]" << std::endl; 
} while (0)

boost::this_thread::sleep(
boost::posix_time::seconds(1));
});
}

boost::thread_group pool;
for (int i = 0; i < 4; ++i) {
pool.create_thread([&service]() { service.run(); });
}
pool.join_all();
}  

然后该程序将按以下顺序进行:
1-主线程:创建io_service实例
2主线程:制作互斥体实例
3主线程:make for循环20次,每次主线程发布一个任务的“lambda函数”,该函数在具有此代码的书中定义为将此函数对象添加到io_service的内部队列中
我的问题是:主线程是否将20个lambda函数对象添加到队列中,在这种情况下,每个线程都会具有一定的i值
然后当新的4个线程开始工作时,他给他们提供了线程函数“run”,它根据同一本书逐一删除函数对象并逐个执行它们
在这种情况下:
线程1:删除lambda 1并使用它自己的代码执行它作为独立实例与唯一的i
线程2:删除lambda 2并使用它自己的代码作为独立实例与独特的i执行它
线程3:删除lambda 3并使用它自己的代码作为独立实例与独特的i执行它
线程4:删除lambda 4并使用它自己的代码作为独立实例与独特的i执行它
然后再次线程一个lambda 5
这是基于我的理解,即队列中有20个函数对象作为lambda函数“可能被封装在一些封装器中”,因此每个线程将采用单独的对象,并且因此不需要互斥“编译后的20个内部汇编代码”

但如果队列中的任务只是对同一个单一代码的引用“但是当它执行for循环”时,则需要互斥体来防止2个线程同时访问关键代码
目前这里的代码符号是哪种情况?


宏在编译时总是被扩展,但编译器只具有非常基本的线程知识(主要是关于能够说某些变量是线程本地的)。

代码只会在实际运行的磁盘映像或内存拷贝中存在一次。

在PRINT_ARGS中锁定互斥锁可确保每个操作的消息完整打印,而不会被另一个线程中断。 (否则,你可能会有一个操作开始打印它的消息,被另一个打印它的消息的线程上的另一个操作中断,然后第一个操作的消息的剩余部分被打印)。

链接地址: http://www.djcxy.com/p/78933.html

上一篇: thread is determined during compile or runtime?

下一篇: std::thread causing application to abort with error R6010