1.线程池
仿照boost::thread_group 实现std::thread_group:
#pragma once
#include <thread>
#include <mutex>
#include <list>
#include <memory>
namespace std
{
//兼容boost::thread_group
//使用std::thread代替boost::thread,std::mutex代替boost::shared_mutex
class thread_group
{
private:
thread_group(thread_group const&);
thread_group& operator=(thread_group const&);
public:
thread_group() {}
~thread_group()
{
for (auto it = threads.begin(), end = threads.end(); it != end; ++it)
{
delete *it;
}
}
template<typename F>
thread* create_thread(F threadfunc)
{
lock_guard<mutex> guard(m);
auto_ptr<thread> new_thread(new thread(threadfunc));
threads.push_back(new_thread.get());
return new_thread.release();
}
void add_thread(thread* thrd)
{
if (thrd)
{
lock_guard<mutex> guard(m);
threads.push_back(thrd);
}
}
void remove_thread(thread* thrd)
{
lock_guard<mutex> guard(m);
auto it = std::find(threads.begin(), threads.end(), thrd);
if (it != threads.end())
{
threads.erase(it);
}
}
void join_all()
{
lock_guard<mutex> guard(m);
for (auto it = threads.begin(), end = threads.end(); it != end; ++it)
{
(*it)->join();
}
}
size_t size() const
{
lock_guard<mutex> guard(m);
return threads.size();
}
private:
list<thread*> threads;
mutable mutex m;
};
}
2 三个版本的计数函数
#include "thread_group_zjd.h"
#include <atomic>
#include <iostream>
#include <string>
#include <time.h>
using namespace std;
// 全局的结果数据
long total = 0;
// 点击函数
void click_normal()
{
for (int i = 0; i < 1000000; ++i)
{
// 对全局数据进行无锁访问
total++;
}
}
atomic<long> total_atomic = 0;
// 点击函数
void click_atomic()
{
for (int i = 0; i < 1000000; ++i)
{
// 对全局数据进行无锁访问
total_atomic++;
}
}
// 对共享资源进行保护的互斥对象
mutex m;
void click_mutex()
{
for (int i = 0; i < 1000000; ++i)
{
// 访问之前,锁定互斥对象
std::lock_guard<mutex> lg(m);
// m.lock();
total++;
// 访问完成后,释放互斥对象
// m.unlock();
}
}
int thread_click(std::function<void()> _func)
{
total = 0;
total_atomic = 0;
// 计时开始
clock_t start = clock();
// 创建100个线程模拟点击统计
std::thread_group threads;
for (int i = 0; i < 100; ++i)
{
threads.create_thread(_func);
}
threads.join_all();
// 计时结束
clock_t finish = clock();
// 输出结果
if (total_atomic)
{
cout << "result:" << total_atomic << endl;
}
else
{
cout << "result:" << total << endl;
}
cout << "duration:" << finish - start << "ms" << endl << endl;
return 0;
}
int main(int argc, char* argv[])
{
string s1;
cout << "请输入,Please input Words(Normal, Mutex or Atomic, Quit to stop) "<<endl;
while (true)
{
getline(cin, s1);
if (s1 == "Normal")
{
thread_click(click_normal);
}
else if (s1 == "Mutex")
{
thread_click(click_mutex);
}
else if (s1 == "Atomic")
{
thread_click(click_atomic);
}
else if (s1 == "Quit")
{
break;
}
else
{
cout << "Input Error" << endl;
}
}
return 0;
}
3 结果总结
Normal版本,多线程计算最快,但数值错误。
Mutex版本,计算耗时极高,数值正确。在c++11 Atomic之前需这样做。
Atomic版本,耗时有很大提升,数值正确。
BTW
使用lock_guard和m.lock的版本耗时有区别,下面截图为使用m.lock(),m.unlock()版本,速度略快;