Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/154.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 在现代c+中,当getter需要将受保护的资源作为共享ptr返回时,如何设计单写多读+;?_C++_Concurrency_C++14_C++17_Mutex - Fatal编程技术网

C++ 在现代c+中,当getter需要将受保护的资源作为共享ptr返回时,如何设计单写多读+;?

C++ 在现代c+中,当getter需要将受保护的资源作为共享ptr返回时,如何设计单写多读+;?,c++,concurrency,c++14,c++17,mutex,C++,Concurrency,C++14,C++17,Mutex,我有一个writer线程在一个对象中写入一个映射,许多reader对象在各自的线程中在映射上执行只读,我当前的设计如下所示 class MyClass { private: shared_ptr<map<int, int>> my_map; mutable shared_mutex mu; public: void update_or_add(pair<int, int> entry); shared_lock<share

我有一个writer线程在一个对象中写入一个映射,许多reader对象在各自的线程中在映射上执行只读,我当前的设计如下所示

class MyClass {
private:
    shared_ptr<map<int, int>> my_map;
    mutable shared_mutex mu;
public:
    void update_or_add(pair<int, int> entry);
    shared_lock<shared_mutex> get_read_lock();
    shared_ptr<const map<int, int>> get_map();
}


void MyClass::update_or_add(pair<int, int> entry) {
    lock_guard<shared_mutex> locker(mu);
    // do update on my_map
}

shared_lock<shared_mutex> MyClass::get_read_lock() {
    shared_lock<shared_mutex> locker(mu);
    return locker;

shared_ptr<const map<int, int>> MyClass::get_map() {
    return my_map;
}
class-MyClass{
私人:
共享我的地图;
可变共享_互斥mu;
公众:
无效更新或添加(配对条目);
共享锁定获取读取锁定();
共享_ptr get_map();
}
void MyClass::更新或添加(配对条目){
锁柜(mu);
//在我的地图上更新吗
}
共享锁定MyClass::get\u read\u lock(){
共享锁柜(mu);
返回储物柜;
共享的\u ptr MyClass::get\u map(){
返回我的地图;
}
下面是我可以如何使用它

//writer
//thread-1
MyClass obj;
while(true) 
obj.update_or_add(entry);

//readers
//thread-2
shared_lock<shared_mutex> locker(obj.get_read_lock());
auto mymap = obj.get_map();
//some computation on mymap
....
//thread-n
shared_lock<shared_mutex> locker(obj.get_read_lock());
auto mymap = obj.get_map();
//some computation on mymap
//编写器
//线程-1
MyClass obj;
while(true)
对象更新或添加(条目);
//读者
//螺纹-2
共享锁柜(obj.get_read_lock());
auto mymap=obj.get_map();
//关于mymap的一些计算
....
//线程-n
共享锁柜(obj.get_read_lock());
auto mymap=obj.get_map();
//关于mymap的一些计算
关于上述问题,我有两个问题

  • 这是使用共享锁和共享互斥锁的正确方法吗
  • 因为我想在read中实现并发性,所以我返回了map的指针并将其传递给其他对象来进行计算,还有其他更好的设计吗

  • 谢谢。

    这里有一个非常简单的共享资源:

    template<class T>
    struct shared_threadsafe {
      template<class F>
      auto read(F&& f)const{
        auto l = lock(); // shared lock
        return f(t); // const access
      }
      template<class F>
      auto write(F&& f){
        auto l = lock(); // exclusive lock
        return f(t); // non-const access
      }
      // construct from a T
      explicit shared_threadsafe( T in ):t(std::forward<T>(in)){}
      // default construct
      shared_threadsafe()=default;
      shared_threadsafe(shared_threadsafe const&)=delete; // it can be written, but don't
      shared_threadsafe& operator=(shared_threadsafe const&)=delete; // it can be written, but don't
      ~shared_threadsafe()=default;
    private:
      mutable std::shared_mutex m;
      T t;
      auto lock() const { return std::shared_lock{m}; }
      auto lock() { return std::unique_lock{m}; }
    }
    
    读卡器线程:

    bob.write([&](auto& bob){ bob.insert( p ); });
    
    bob.read([&](auto& bob){
      // cos=de that reads from the map `bob`
    });
    
    如果读取器线程具有
    const
    引用或指针,则它们仅具有读取权限

    实际上,我会想出一些操作,让共享线程安全在某个类中是私有的,并且只公开这些操作

    通常,公开完整的读/写锁表明您的代码级别还不够高。基于锁的并发无法组合,也无法很好地扩展。当您公开在锁中运行任意代码的能力时,您会鼓励组合,这是一场灾难

    我的共享threadsafe是一个尝试性的折衷方案,因为锁代码至少编写了一次,并且基于范围。我隐藏它是因为它仍然没有编写

    根据您的读/写操作以及延迟的成本,移动到争用副本版本也可能是明智的。在此计划下,读卡器将获得指向其具有完全常量访问权限的表的智能指针。写卡器以写方式复制(cow)如果存在争用,则执行快速更新。写入时拷贝结果仅对写入发生后出现的读者可见

    手写(非std)映射可以进行部分cow更新,共享表中新旧读取之间保持不变的部分

    但在这一点上,您开始考虑DB。无论如何,您应该从DB开始。

    “一些计算”-什么计算?一般来说,好的线程安全设计并不能构成。而公开读或写锁的API也不能扩展。
    bob.read([&](auto& bob){
      // cos=de that reads from the map `bob`
    });