我执行了以下程序,其中我创建了 100 个线程并发执行。 请注意这是一个示例程序。我知道下面的程序不需要多线程,但我的目的是测试互斥量。
class ThreadPool{
public:
ThreadPool(int num = 10);
~ThreadPool();
void AssignPool();
void doSometask();
void inc();
private:
boost::asio::io_service ioService;
boost::thread_group threadpool;
boost::asio::io_service::work * work;
volatile int p_size;
int pool_sz;
boost::mutex io_mutex;// with boost lock
};
void ThreadPool::AssignPool()
{
std::cout<<std::endl<<"pool_sz="<<pool_sz<<std::endl;
for(int i=0;i<pool_sz;i++)
{
ioService.post(boost::bind(&ThreadPool::doSometask, this));
}
}
void ThreadPool::inc()
{
p_size++;
}
void ThreadPool::doSometask()
{
// boost::mutex::scoped_lock lock(io_mutex);
for(int i=0;i<10000;i++){
inc();
}
}
ThreadPool::ThreadPool(int num):p_size(0)
{
pool_sz = num;
work = new boost::asio::io_service::work(ioService);
for(int i =0;i<num;i++)
{
threadpool.create_thread(boost::bind(&boost::asio::io_service::run, &ioService )) ;
}
}
ThreadPool::~ThreadPool()
{
delete work;
ioService.stop();
threadpool.join_all();
}
int main()
{
ThreadPool p1(100);
p1.AssignPool();
}
案例 1: 上面的程序是通过注释“boost::mutex::scoped_lock lock(io_mutex);”来执行的行是“无互斥情况”。 程序花费的时间是
real 0m1.386s
user 0m0.483s
sys 0m9.937s
案例 2:使用 Mutex: 然而,当我用互斥体运行这个程序时,即“boost::mutex::scoped_lock lock(io_mutex);”线。该程序花费的时间更少。
real 0m0.289s
user 0m0.067s
sys 0m0.230s
根据我对互斥锁的理解,程序应该比没有互斥锁花费更多的时间。这里出了什么问题??
最佳答案
在您的示例中,您将互斥锁锁定在 doSometask()
中, 并且因此一直只有一个线程在运行并且它会在屈服于另一个任务之前完成 for 循环。因此,该程序按字面意义串行运行,不会发生缓存脱粒。
如果没有锁,所有线程都将在获得处理器时间时运行,并且假设处理器的数量明显低于 100,那么所有级别的缓存阈值都将进行(如 Bo Persson 在评论中所写) ,这将增加运行时间。
衡量锁定对运行时间影响的更好方法是 (a) 只运行与计算机内核数量相同的线程,以便最大限度地减少由于上下文切换而导致的缓存阈值,以及 (b)将锁放入 ThreadPool::inc()
方法,以便更频繁地进行同步。
作为奖励,您可以通过声明 p_size
来正确运行无锁方法。作为std::atomic<int>
(C++11) 并查看基于互斥锁的同步与使用原子的影响。
关于c++ - Boost::mutex 比没有 mutex 的程序花费的时间更少,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/43182719/