【问题标题】:MongoDB C++: Is mongocxx::pool thread safe?MongoDB C++:mongocxx::pool 线程安全吗?
【发布时间】:2017-01-04 14:22:42
【问题描述】:

在获取连接时是否必须手动锁定 mongocxx::pool?

即这安全吗? (从 Mongo 网站复制的示例)

mongocxx::instance instance{};
mongocxx::pool pool {mongocxx::uri{}};

using mongocxx::pool::entry = std::unique_ptr<client, std::function<void (client*)>>

auto threadfunc = [](mongocxx::client &client, stdx::string_view dbname) {
    client[dbname]["col"].insert({});
}
// don't even bother sharing clients. Just give each thread its own,
std::thread([]() {
    // pool.acquire() returns a mongo::pool::entry type
    mongocxx::client *c= pool.acquire().get();
    threadfunc(*c, "db1");
    threadfunc(*c, "db2");
});

std::thread([]() {
    mongocxx::client *c = pool.acquire().get();;
    threadfunc(*c, "db2");
    threadfunc(*c, "db1");
});

【问题讨论】:

    标签: c++ multithreading mongodb mongo-cxx-driver


    【解决方案1】:

    是的,mongocxx::pool 是线程安全的。您可以从多个线程同时访问它。但是,从池中返回的各个 mongocxx::client 对象不是线程安全的,从 client 获得的从属对象(如 collectiondatabase)也不是 - 您不得共享它们线程之间。

    另请注意,您的示例(不是从网站逐字复制,而是根据其中一个示例进行了修改)包含严重的编程错误。

    这一行:

       mongocxx::client *c= pool.acquire().get();
    

    将获得一个池条目,然后从中提取一个裸指针。但是,池条目将在语句结束时被销毁,导致底层 client 对象返回到池中,从而允许另一个线程在您继续使用它时可能会拾取它。

    你应该这样写:

    mongocxx::instance instance{};
    mongocxx::pool pool {mongocxx::uri{}};
    
    auto threadfunc = [](mongocxx::client &client, stdx::string_view dbname) {
        client[dbname]["col"].insert({});
    }
    // don't even bother sharing clients. Just give each thread its own,
    std::thread([]() {
        // pool.acquire() returns a mongo::pool::entry type
        auto c = pool.acquire();
        threadfunc(*c, "db1");
        threadfunc(*c, "db2");
    });
    
    std::thread([]() {
        auto c = pool.acquire();
        threadfunc(*c, "db2");
        threadfunc(*c, "db1");
    });
    

    这样,每个线程都会保留池条目,直到它使用完毕,此时当c中的unique_ptr被销毁时,它会自动返回。

    【讨论】:

    • @xcorat 为您提出的问题点赞和/或接受最佳答案是有礼貌的。
    • 天哪!我刚刚阅读了答案:p(jk,但是是的,我刚刚阅读了它,谢谢 :)
    • 是的,我最终将代码更改为您修复它的方式,并认为我编辑了问题,但我想我没有。再次感谢!
    猜你喜欢
    • 2018-12-22
    • 2011-09-28
    • 1970-01-01
    • 2019-09-20
    • 2021-01-15
    • 2010-11-24
    • 2019-05-23
    • 2011-01-22
    • 1970-01-01
    相关资源
    最近更新 更多