缓存线程的这种通用实现安全吗(C ++)?

时间:2019-01-23 23:47:28

标签: c++ templates thread-safety c++17

我编写了以下通用缓存的实现,其中#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的书,我的理解是仅在修改数据时才需要使用互斥量。因此,在映射中,由于对于给定的键,指向值的指针将始终是相同的(由于使用了哈希函数),因此,如果键存在,则无需锁定。

1 个答案:

答案 0 :(得分:6)

出于多种原因,此实现不是线程安全的。

GetOf()的前半部分调用std::map实例的方法。 std::map的方法都不是线程安全的,GetOf()的后半部分修改std::map

由于互斥锁不保护Getof()的前半部分(调用上述方法),因此这不是线程安全的。

Clear()也修改了std::map,也没有任何同步/互斥保护。

P.S。不需要在析构函数中调用std::map::clear()