我编写了以下通用缓存的实现,其中#pragma once
#include "stdafx.h"
#include <map>
#include <functional>
#include <mutex>
using namespace std;
template<class T1, class T2>
class __declspec(dllexport) CacheOf
{
map<T1, T2> _cache;
function<T2(T1)> _func;
mutex CacheMtx;
public:
CacheOf(function<T2(T1)> func);
~CacheOf();
T2 Get(T1);
void Clear();
};
template <class T1, class T2>
CacheOf<T1, T2>::CacheOf(std::function<T2(T1)> func)
{
_func = func;
}
template <class T1, class T2>
CacheOf<T1, T2>::~CacheOf()
{
_cache.clear();
}
template <class T1, class T2>
auto CacheOf<T1, T2>::Get(T1 key) -> T2
{
auto it = _cache.find(key);
T2 value;
if (it != _cache.end())
{
value = it->second;
return value;
}
value = _func(key);
{
unique_lock<mutex> cachelock(CacheMtx);
_cache.insert(pair<T1, T2>(key, value));
}
return value;
}
template <class T1, class T2>
auto CacheOf<T1, T2>::Clear() -> void
{
_cache.clear();
}
将提供值(计算,读取文件等)。 线程安全吗?
insert
编辑:对于上下文,我将使用此类添加以下条件:
对于给定的键,值始终相同
我是否仅在var json = resp.getContentText();
var data = JSON.parse(json);
时锁定?在插入的同时读取存储在映射中的某个键值是否可以?允许两个线程同时插入也是可以的(这样可以避免使用互斥锁)吗?
根据Butenhoff的书,我的理解是仅在修改数据时才需要使用互斥量。因此,在映射中,由于对于给定的键,指向值的指针将始终是相同的(由于使用了哈希函数),因此,如果键存在,则无需锁定。>
答案 0 :(得分:6)
出于多种原因,此实现不是线程安全的。
GetOf()
的前半部分调用std::map
实例的方法。 std::map
的方法都不是线程安全的,GetOf()
的后半部分修改std::map
。
由于互斥锁不保护Getof()
的前半部分(调用上述方法),因此这不是线程安全的。
Clear()
也修改了std::map
,也没有任何同步/互斥保护。
P.S。不需要在析构函数中调用std::map::clear()
。