完整示例:
本节给出有关IDCreator的完整代码。包含以下示例内容:
①通过宏标识只允许单一线程执行的代码;
②一个互斥量锁两处代码;
③两个互斥量各锁各的代码;
④读写操作间的简单同步;
⑤可变的成员数据;
⑥并发环境下单例对象的使用;
⑦两个线程目标过程之间的数据同步(一个线程修改“_id”的值,另一线程反复读取该值,并以此确定是否结束线程)。
#include <iostream>
#include <set>
#include <vector>
#include <future>
#include <mutex>
#include <sstream>
#define __concurrency_mutex_block_begin__
using namespace std;
struct COutWithMutex
{
public:
static COutWithMutex& Get()
{
static COutWithMutex instance;
return instance;
}
void PrintLn(string const& line) ///加锁输出
{
__concurrency_mutex_block_begin__
{
lock_guard <mutex> g(_m);
cout << line << endl;
}
}
private:
COutWithMutex() = default;
mutex _m;
};
struct IDCreator
{
public:
static IDCreator& Instance()
{
static IDCreator instance;
return instance;
}
int GetNewID() ///加锁版
{
__concurrency_mutex_block_begin__
{
lock_guard <mutex> lock(_m);
return GetNewIDWithoutLock();
}
}
int GetID() const ///加锁版
{
__concurrency_mutex_block_begin__
{
lock_guard <mutex> lock(_m);
return GetIDWithoutLock();
}
}
protected:
int GetNewIDWithoutLock() ///不加锁版
{
return ++ _id;
}
int GetIDWithoutLock() const ///不加锁版
{
return _id;
}
private:
IDCreator()
: _id(0)
{
}
int _id;
mutable mutex _m;
};
int get_new_user_id()
{
return IDCreator::Instance().GetNewID(); ///加锁的
}
#define MAX_USER_ID 1000
void test()
{
typedef future <int> IntFuture;
vector <IntFuture> futures;
for(int i = 0; i < MAX_USER_ID; ++ i)
{
IntFuture f = async(get_new_user_id); ///1000个异步执行的函数
futures.push_back(std::move(f)); ///future不允许复制
}
set <int> ids;
for(auto& f : futures) ///auto&使用引用,因为future不允许复制
{
int id = f.get();
// stringstream ss;
// ss << "生成的id是:" << id;
// COutWithMutex::Get().PrintLn(ss.str());
if(ids.find(id) != ids.end())
{
stringstream ss;
ss << "该ID已经存在了:" << id << ".";
COutWithMutex::Get().PrintLn(ss.str());
continue;
}
ids.insert(id);
}
}
void output_current_user_id()
{
while(true) ///不停的读取当前id,直到当前id为最大时停止
{
int id = IDCreator::Instance().GetID();
stringstream ss;
ss << "当前ID是 " << id << ".";
COutWithMutex::Get().PrintLn(ss.str());
if(id == MAX_USER_ID)
{
break;
}
}
}
int main()
{
/**< output_current_user_id是一个不停地读取当前id的函数,
所以可以输出很多id */
future <void> f = async(output_current_user_id);
test();
f.wait();
return 0;
}