4

接続の取得中に mongocxx::pool を手動でロックする必要がありますか?

つまり、これは安全ですか?(モンゴのウェブサイトからコピーした例)

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");
});
4

1 に答える 1

9

はい、mongocxx::poolスレッドセーフです。複数のスレッドから同時にアクセスできます。ただし、mongocxx::clientプールから返された個々のオブジェクトはスレッドセーフではなく、従属オブジェクトは のようなものでcollection取得databaseされたものでclientもありません。それらをスレッド間で共有してはなりません。

あなたの例(ウェブサイトから逐語的にコピーされたものではなく、例の1つから変更されたもの)には、重大なプログラミングエラーが含まれていることにも注意してください。

この行:

   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");
});

こうすることで、各スレッドは使用が終了するまでプール エントリを保持し、その時点でunique_ptrincが破棄されると自動的に返されます。

于 2017-01-05T03:03:14.163 に答える