Является ли эта общая реализация потока кеша безопасной (c ++)? - PullRequest
0 голосов
/ 24 января 2019

Я написал следующую реализацию универсального кэша, где func будет предоставлять значения (вычислять, читать файл и т. Д.). Это потокобезопасно?

#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();
}

РЕДАКТИРОВАТЬ: Для контекста я буду использовать этот класс, я добавляю следующее условие:

для данного ключа,значение всегда одинаково

Разве я не должен блокироваться только при I insert?Хорошо ли читать определенное значение ключа, хранящееся на карте, при одновременной вставке?Также хорошо, что 2 потока одновременно выполняют вставку (поэтому я могу избежать использования мьютекса)?

Насколько я понимаю из книги Бутенхоффа, нам нужно использовать мьютекс только тогда, когда мы изменяемданные.Поэтому в карте из-за того, что для данного ключа указатель на значение всегда будет одинаковым (благодаря хэш-функции), поэтому, если ключ существует, мне не нужно блокировать.

1 Ответ

0 голосов
/ 24 января 2019

Эта реализация не является поточно-ориентированной по нескольким причинам.

Первая половина GetOf() вызывает методы экземпляра std::map.Ни один из std::map методов не является поточно-ориентированным, а вторая половина GetOf() не изменяет std::map.

, так как мьютекс не защищает первую половину Getof(), где вышеупомянутые методыполучить вызов, это не потокобезопасно.

Clear() также изменяет std::map, без какой-либо синхронизации / защиты мьютекса, либо.

PS Вызов std::map::clear() вдеструктор не нужен.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...